% \iffalse
%<*driver>
\ProvidesFile{polytable.drv}
\documentclass{ltxdoc}
\usepackage{polytable}
\begin{document}
   \DocInput{polytable.dtx}
\end{document}
%</driver>
%
% Copyright (C) 2003--2004 by Andres Loeh
%
% \fi
%
% \ProvidesFile{polytable.dtx}
%   [2003/12/26 v0.7.2 `polytable' package (Andres Loeh)]
% \GetFileInfo{polytable.dtx}
%
% \title{The \textsf{polytable} package}
% \author{Andres L\"oh\\ \texttt{polytable@andres-loeh.de}}
% \date{\filedate}
%
% \maketitle
%
% \begin{abstract}
% This package implements a variant of tabular-like environments
% where columns can be given a name and entries can flexibly
% be placed between arbitrary columns. Complex alignment-based
% layouts, for example for program code, are possible.
% \end{abstract}
%
% \changes{v0.1}{2002/11/17}{Works.}
% \changes{v0.2}{2003/04/03}{Added pboxed. Added debug option.}
% \changes{v0.3}{2003/05/26}{Greatly enhanced pboxed.}
% \changes{v0.4}{2003/06/11}{Optional argument for ptable and parray.}
% \changes{v0.4.1}{2003/07/13}{Saving and restoring enhancements.}
% \changes{v0.4.2}{2003/07/16}{Fixed bug that caused infinite reruns.}
% \changes{v0.4.3}{2003/07/20}{Added some missing relaxes.}
% \changes{v0.5}{2003/07/22}{Documentation improved. To be put on CTAN.}
% \changes{v0.6}{2003/07/24}{Depends on lazylist instead of lambda now.}
% \changes{v0.7}{2003/11/20}{Check for undefined columns. Save counters.}
% \changes{v0.7.1}{2003/12/26}{Counters have not been restored correctly.}
%
% \section{Introduction}
%
% This package implements a variant of tabular-like environments.
% We will call these environments the |poly|-environments to
% distinguish them from the standard ones as provided by the
% \LaTeX\ kernel or the \textsf{array} package.
%
% Other than in standard tables, each column has a name. For
% instance, the commands\\
% |\column{foo}{l}|\\
% |\column{bar}{r}|\\
% -- when used within a |poly|-environment -- define a column
% with name |foo| that is left-aligned, and a column with name
% |bar| that is right-aligned.
%
% Once a couple of columns have been defined, the text is specified
% in a series of |\fromto| commands. Instead of specifying text
% per column in order, separating columns with |&|, we give the
% name of the column where the content should start, and the name
% of the column before which the content should stop.
% To typeset the text ``I'm aligned!'' in the column |foo|,
% we could thus use the command\\
% |\fromto{foo}{bar}{I'm aligned}|\\
% Several |\fromto|-commands can be used to typeset a complete
% line of the table. A new line can be started with |\nextline|.
%
% The strength of this approach is that it implicitly handles
% cases where different lines have different alignment properties.
% Not all column names have to occur in all lines.
% 
% \section{A complete example}
%
% Figure~\ref{tab:example} 
% is an example that is designed to show the
% capabilities of this package. In particular, it is \emph{not}
% supposed to look beautiful.
%
% \begin{figure}[htb]
% \centering
% \begin{ptabular}
% \column{left}{|l|}
% \column{right}{l|}
% \column{m13}{l|}
% \column{m23}{l|}
% \column{m33}{l|}
% \column{m12}{r|}
% \column{m22}{r|}
% \column{end}{l}
% \fromto{left}{m13}{left}
% \fromto{m13}{m23}{first of three}
% \fromto{m23}{m33}{second of three}
% \fromto{m33}{right}{third of three}
% \fromto{right}{end}{right}
% \nextline
% \fromto{left}{m12}{left}
% \fromto{m12}{m22}{middle 1/2}
% \fromto{m22}{right}{middle 2/2}
% \fromto{right}{end}{right}
% \nextline
% \fromto{left}{m13}{left}
% \fromto{m13}{m23}{middle 1/3}
% \fromto{m23}{m33}{middle 2/3}
% \fromto{m33}{right}{middle 3/3}
% \fromto{right}{end}{right}
% \nextline
% \fromto{left}{m12}{left}
% \fromto{m12}{m22}{first of two middle columns}
% \fromto{m22}{right}{second of two middle columns}
% \fromto{right}{end}{right}
% \end{ptabular}
% \caption{Example table}%
% \label{tab:example}
% \end{figure}
%
% The example table consists of four lines. All lines have
% some text on the left and on the right, but the middle part
% follows two different patterns: the first and the third line
% have three middle columnss that should be aligned, the second
% and the fourth line have two (right-aligned) middle columns 
% that should be aligned, but otherwise independent of the three 
% middle columns in the other lines.
%
% Vertical bars are used to clarify where one column ends and
% the next column starts in a particular line. Note that the first
% and the third line are completely aligned. Likewise, the
% second and the fourth line are. However, the fact that the
% bar after the text ``middle 1/2'' ends up between the two
% bars delimiting the column with ``second of three'' in it
% is just determined by the length of the text ``first of two
% middle columns'' in the last line. This text fragment
% is wider than the first of the three middle columns, but not
% wider than the first two of the three middle columns.
%
% Let's have a look at the input for the example table:
% \begin{verbatim}
% \begin{ptabular}
% \column{left}{|l|}
% \column{right}{l|}
% \column{m13}{l|}
% \column{m23}{l|}
% \column{m33}{l|}
% \column{m12}{r|}
% \column{m22}{r|}
% \column{end}{l}
% \fromto{left}{m13}{left}
% \fromto{m13}{m23}{first of three}
% \fromto{m23}{m33}{second of three}
% \fromto{m33}{right}{third of three}
% \fromto{right}{end}{right}
% \nextline
% \fromto{left}{m12}{left}
% \fromto{m12}{m22}{middle 1/2}
% \fromto{m22}{right}{middle 2/2}
% \fromto{right}{end}{right}
% \nextline
% \fromto{left}{m13}{left}
% \fromto{m13}{m23}{middle 1/3}
% \fromto{m23}{m33}{middle 2/3}
% \fromto{m33}{right}{middle 3/3}
% \fromto{right}{end}{right}
% \nextline
% \fromto{left}{m12}{left}
% \fromto{m12}{m22}{first of two middle columns}
% \fromto{m22}{right}{second of two middle columns}
% \fromto{right}{end}{right}
% \end{ptabular}
% \end{verbatim}
% First, columns are declared, including the vertical lines.
% Note that there is a final column |end| being declared
% that is only used as the end column in the |\fromto| statements.
% A future version of this package 
% will probably get rid of the need to define
% such a column.
% After the column definitions, the lines are typeset by a
% series of |\fromto| commands, separated by |\nextline|.
% Note that the first and third column do not use |m12|, |m22|.
% Similarly, the second and fourth column do not use
% |m13|, |m23|, and |m33|.
%
% So far, one could achieve the same with an ordinary |table|
% environment. The table would have 6 columns. One left and right,
% the other four for the middle: the first and third line would
% use the first of the four columns, then place the second entry
% in a |\multicolumn| of length 2, and then use the fourth column
% for the third entry. Likewise, the other lines would place both
% their entries in a |\multicolumn| of length 2. In fact, this
% procedure is very similar to the way the |ptabular| environment
% is implemented.
%
% The problem is, though, that we need the information that
% the first of the two middle columns ends somewhere in the middle
% of the second of the three columns, as observed above. If we
% slightly modify the texts to be displayed in the middle columns,
% this situation changes. Figure~\ref{tab:variation} shows
% two variants of the example table. The input is the same,
% only that the texts contained in some columns have slightly
% changed. As you can see, the separator between the first and
% second middle column in the second and fourth lines of the
% tables now once ends up within the first, once within the
% third of the three middle columns of the other lines.
%
% \begin{figure}[htb]
% \centering
% \begin{ptabular}
% \column{left}{|l|}
% \column{right}{l|}
% \column{m13}{l|}
% \column{m23}{l|}
% \column{m33}{l|}
% \column{m12}{r|}
% \column{m22}{r|}
% \column{end}{l}
% \fromto{left}{m13}{left}
% \fromto{m13}{m23}{first of three}
% \fromto{m23}{m33}{second of three}
% \fromto{m33}{right}{third of three}
% \fromto{right}{end}{right}
% \nextline
% \fromto{left}{m12}{left}
% \fromto{m12}{m22}{middle 1/2}
% \fromto{m22}{right}{middle 2/2}
% \fromto{right}{end}{right}
% \nextline
% \fromto{left}{m13}{left}
% \fromto{m13}{m23}{middle 1/3}
% \fromto{m23}{m33}{middle 2/3}
% \fromto{m33}{right}{middle 3/3}
% \fromto{right}{end}{right}
% \nextline
% \fromto{left}{m12}{left}
% \fromto{m12}{m22}{first of two}
% \fromto{m22}{right}{second of two}
% \fromto{right}{end}{right}
% \end{ptabular}
% \par\bigskip
% \begin{ptabular}
% \column{left}{|l|}
% \column{right}{l|}
% \column{m13}{l|}
% \column{m23}{l|}
% \column{m33}{l|}
% \column{m12}{r|}
% \column{m22}{r|}
% \column{end}{l}
% \fromto{left}{m13}{left}
% \fromto{m13}{m23}{first of three}
% \fromto{m23}{m33}{second of three}
% \fromto{m33}{right}{third of three}
% \fromto{right}{end}{right}
% \nextline
% \fromto{left}{m12}{left}
% \fromto{m12}{m22}{middle 1/2}
% \fromto{m22}{right}{middle 2/2}
% \fromto{right}{end}{right}
% \nextline
% \fromto{left}{m13}{left}
% \fromto{m13}{m23}{middle 1/3}
% \fromto{m23}{m33}{middle 2/3}
% \fromto{m33}{right}{middle 3/3}
% \fromto{right}{end}{right}
% \nextline
% \fromto{left}{m12}{left}
% \fromto{m12}{m22}{the first of two middle columns}
% \fromto{m22}{right}{2/2}
% \fromto{right}{end}{right}
% \end{ptabular}
% \caption{Variants of the example table}%
% \label{tab:variation}
% \end{figure}
%
% If one wants the general case using the |\multicolumn|
% approach, one thus has to measure the widths of the entries
% of the columns to compute their relative position. In essence,
% this is what the package does for you.
%
% \section{Haskell code example}
%
% I have written this package mainly for one purpose: to be able
% to beautifully align Haskell source code. Haskell is a functional
% programming language where definitions are often grouped into
% several declarations. I've seen programmers exhibit symmetric
% structures in different lines by adding spaces in their source
% code files in such a way that corresponding parts in different
% definitions line up. On the other hand, as Haskell allows
% user-defined infix operators, some programmers like their symbols
% to be typeset as \LaTeX\ symbols, not as typewriter code.
% But using \LaTeX\ symbols and a beautiful proportional font
% usually destroys the carefully crafted layout and alignment.
%
% With lhs2\TeX, there is now a preprocessor available that preserves
% the source code's internal alignment by mapping the output onto
% \textsf{polytable}'s environments. 
% Figure~\ref{tab:haskell} is an example of how
% the output of lhs2\TeX\ might look like.
%
% \newcommand{\HsVar}[1]{\mathop{\mathit{\strut #1}}}
% \newcommand{\HsCon}[1]{\mathop{\mathsf{\strut #1}}}
% \newcommand{\HsKey}[1]{\mathop{\mathbf{\strut #1}}}
% \newcommand{\map}{\HsVar{map}}
% \newcommand{\round}{\HsVar{round}}
% \newcommand{\TA}{\HsVar{a}}
% \newcommand{\TB}{\HsVar{b}}
% \newcommand{\TF}{\HsVar{f}}
% \newcommand{\TX}{\HsVar{x}}
% \newcommand{\TY}{\HsVar{y}}
% \newcommand{\TN}{\HsVar{n}}
% \newcommand{\TM}{\HsVar{m}}
% \newcommand{\TR}{\HsVar{r}}
% \newcommand{\TXS}{\HsVar{xs}}
% \newcommand{\RealFrac}{\mathop{\mathsf{RealFrac}}}
% \newcommand{\Integral}{\mathop{\mathsf{Integral}}}
% \newcommand{\LET}{\mathop{\mathbf{let}}}
% \newcommand{\IN}{\mathop{\mathbf{in}}}
% \newcommand{\IF}{\mathop{\mathbf{if}}}
% \newcommand{\THEN}{\mathop{\mathbf{then}}}
% \newcommand{\ELSE}{\mathop{\mathbf{else}}}
% \newcommand{\OF}{\mathop{\mathbf{of}}}
% \newcommand{\CASE}{\mathop{\mathbf{case}}}
% \newcommand{\CLASS}{\mathop{\mathbf{class}}}
% \newcommand{\WHERE}{\mathop{\mathbf{where}}}
% \newcommand{\Eq}{\mathop{\mathsf{Eq}}}
% \newcommand{\Ord}{\mathop{\mathsf{Ord}}}
%
% \setlength{\arraycolsep}{.5ex}
%
% \begin{figure}
% \[
% \begin{parray}
% \column{left}{l}
% \column{body}{l}
% \column{end}{l}
% \column{rel}{c}
% \column{rhs}{l}
% \fromto{left}{end}{\CLASS\ (\Eq\TA)\Rightarrow\Ord\TA\WHERE}
% \nextline
% \fromto{left}{body}{\qquad\ }
% \fromto{body}{rel}{\HsVar{compare}}
% \fromto{rel}{rhs}{::}
% \fromto{rhs}{end}{\TA\rightarrow\TA\rightarrow\HsCon{Ordering}}
% \nextline
% \fromto{left}{body}{\qquad\ }
% \fromto{body}{rel}{(<),(\leq),(\geq),(>)}
% \fromto{rel}{rhs}{::}
% \fromto{rhs}{end}{\TA\rightarrow\TA\rightarrow\HsCon{Bool}}
% \nextline
% \fromto{left}{body}{\qquad\ }
% \fromto{body}{rel}{\HsVar{max},\HsVar{min}}
% \fromto{rel}{rhs}{::}
% \fromto{rhs}{end}{\TA\rightarrow\TA\rightarrow\HsCon{Bool}}
% \nextline
% \nextline
% \fromto{body}{end}{\mbox{--- Minimal complete definition: 
%   $(\leq)$ or $\HsVar{compare}$}}
% \nextline
% \fromto{body}{end}{\mbox{--- using $\HsVar{compare}$ can be more efficient
%   for complex types}}
% \nextline
% \column{cgrd}{l}
% \fromto{body}{cgrd}{\HsVar{compare}\TX\TY}
% \fromto{cgrd}{rel}{\vert\ \TX\equiv\TY}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\HsCon{EQ}}
% \nextline
% \fromto{cgrd}{rel}{\vert\ \TX\leq\TY}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\HsCon{LT}}
% \nextline
% \fromto{cgrd}{rel}{\vert\ \HsVar{otherwise}}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\HsCon{GT}}
% \nextline
% \fromto{body}{rel}{\TX\leq\TY}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\HsVar{compare}\TX\TY\not\equiv\HsCon{GT}}
% \nextline
% \fromto{body}{rel}{\TX < \TY}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\HsVar{compare}\TX\TY\equiv\HsCon{LT}}
% \nextline
% \fromto{body}{rel}{\TX\geq\TY}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\HsVar{compare}\TX\TY\not\equiv\HsCon{LT}}
% \nextline
% \fromto{body}{rel}{\TX > \TY}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\HsVar{compare}\TX\TY\equiv\HsCon{GT}}
% \nextline
% \fromto{body}{cgrd}{\HsVar{max}\TX\TY}
% \fromto{cgrd}{rel}{\vert\ \TX\leq\TY}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\TY}
% \nextline
% \fromto{cgrd}{rel}{\vert\ \HsVar{otherwise}}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\TX}
% \nextline
% \fromto{body}{cgrd}{\HsVar{min}\TX\TY}
% \fromto{cgrd}{rel}{\vert\ \TX\leq\TY}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\TX}
% \nextline
% \fromto{cgrd}{rel}{\vert\ \HsVar{otherwise}}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\TY}
% \end{parray}
% \]
% \caption{Haskell code example}
% \label{tab:haskell}
% \end{figure}
%
% Of course, this could be useful for other programming languages
% as well. In fact, lhs2\TeX\ can be tweaked to process several
% experimental languages that are based on Haskell, but I can imagine
% that this package could generally prove useful to typeset program
% code.
%
% \section{Other applications}
%
% Although I have written this package for a specific purpose, I
% am very much interested to hear of other potential application
% areas. Please tell me if you found a use for this package and
% do not hesitate to ask for additional features that could convince
% you to use the package for something.
%
% \section{The \textsf{lazylist} package}
%
% Internally, this package makes use of Alan Jeffrey's excellent
% \textsf{lazylist} package, which provides an implementation of
% the lambda calculus using fully expandable control sequences.
% Unfortunately, |lazylist.sty| is not included in most common
% \TeX\ distributions, so you might need to fetch it from CTAN 
% separately.
%
% \section{Reference}
%
% \subsection{The environments}
%
% \DescribeEnv{ptabular}
% \DescribeEnv{parray}
% \DescribeEnv{pboxed}
% There are currently three environments that this package provides:
% |ptabular| and |parray| are based on (and translated into) the usual
% |tabular| and |array| environments as provided by the |array|
% package. In particular, |parray| assumes math mode, whereas
% |ptabular| assumes text mode. The third environment, |pboxed|,
% typesets the material in boxes of the calculated length, but in
% normal paragraph mode. The advantage is that
% there can be page breaks within the table. 
% Note that you should start a new, nonindented
% paragraph before beginning a |pboxed|. All lines in a |pboxed|
% should be of equal length, so it might be possible to center
% or right-align the material, although this has not been
% extensively tested.
%
% One more environment is planned: |plongtable|, a poly-version
% of the |longtable| environment.
%
% The interface is the same for all of the environments.
%
% \subsection{The commands}
%
% In each of the environments, the following commands can be
% used (and \emph{only} these commands should be used):
%
% \DescribeMacro{\column}
% With |\column{|\meta{columnid}|}{|\meta{spec}|}|, a new column
% \meta{columnid} is specified. The name of the column can be
% any sequence of alphanumerical characters. The \meta{spec} is
% a format string for that particular column, and it can contain
% the same constructs that can be used in format strings of normal
% tables or arrays (this also holds for the |pboxed| environment).
% However, it should only contain the description for \emph{one}
% column. (I've never tested what happens if you do something else,
% but you have been warned \dots)
%
% If the save/restore feature (explained below) is not used, |\column|
% definitions are always local to one table.
% One can define a column multiple times within one table. 
% A warning will be produced, 
% and the second format string will be used for the complete table.
%
% \DescribeMacro{\fromto}
% The call |\fromto{|\meta{fromid}|}{|\meta{toid}|}{|\meta{text}|}|
% will typeset \meta{text} in the current line, starting at column
% \meta{fromid} and ending before column \meta{toid}, using the
% format string specified for \meta{fromid}.
%
% A line of a table usually consists of multiple |\fromto| statements.
% Each statement's starting column should be either the same as the
% end column of the previous statement, or it will be assumed that
% the start column is located somewhere to the right of the previous
% end column. The user is responsible to not introduce cycles in the
% (partial) order of columns. If such a cycle is specified, the
% current algorithm will loop, causing a |dimension too large| error
% ultimately. TODO: catch this error.
%
% \DescribeMacro{\nextline}
% The command |\nextline| ends one line and begins the next.
% There is no need to end the last line. One can pass an optional
% argument, as in |\nextline[|\meta{dimen}|]|, that will add
% \meta{dimen} extra space between the lines. TODO: make this
% command available as |\\|.
%
% \subsection{A warning}
%
% The contents of the table are processed multiple times because
% the widths of the entries are measured. Global assigments that
% modify registers and similar things can thus result in unexpected
% behaviour. 
% New in v0.7: \LaTeX\ counters (i.e. counters defined by
% |\newcounter|) are protected now. They will be reset after
% each of the trial runs.
% 
% \subsection{Saving column width information}
%
% WARNING: this feature does \emph{only} work correctly with
% the |pboxed| environment right now. TODO: make this work
% with the other environments (this essentially amounts to
% implementing a |tabbing|-like |\kill| statement for |tabular|
% and |array|; does that already exist somewhere?).
%
% Sometimes, one might want to reuse not only the same column, but
% exactly the same alignment as in a previous table. An example
% would be a fragment of program code, which has been broken into
% several pieces, with documentation paragraphs added in between.
%
% \DescribeMacro{\savecolumns}
% \DescribeMacro{\restorecolumns}
% With |\savecolumns[|\meta{setid}|]|, one can save the information
% of the current table for later reuse. The name |setid| can be an
% arbitrary sequence of alphanumeric characters. It does \emph{not} share
% the same namespace as the column names. The argument is optional;
% if it is omitted, a default name is assumed. Later, one can restore
% the information (multiple times, if needed) in other tables, by
% issuing a |\restorecolumns[|\meta{setid}|]|.
%
% This feature requires to pass information backwards in the general
% case, as column widths in later environments using one specific
% column set might influence the layout of earlier environments.
% Therefore, information is written into the |.aux| file, and
% sometimes, a warning is given that a rerun is needed. Multiple
% reruns might be required to get all the widths right.
%
% I have tried very hard to avoid producing rerun warnings infinitely
% except if there are really cyclic dependencies between columns.
% Still, if it happens or something seems to be broken, it often
% is a good idea to remove the |.aux| file and start over. Be sure
% to report it as a bug, though.
%
% Figure~\ref{tab:saverestore} is an example of the Haskell code
% example with several comments inserted. The source of this file
% shows how to typeset the example.
% \begin{figure}
% \setlength{\parindent}{0pt}%
% \setlength{\parskip}{1ex}%
% \hrule
% We introduce a new type class $\Ord$ for objects that admit
% an ordering. It is based on the $\Eq$ class:
%
% \(
% \begin{pboxed}
% \savecolumns
% \column{left}{>{\quad}l}
% \column{end}{l}
% \fromto{left}{end}{\CLASS\ (\Eq\TA)\Rightarrow\Ord\TA\WHERE}
% \end{pboxed}
% \)
%
% The next three lines give the type signatures for all
% the methods of the class.
%
% \(
% \begin{pboxed}
% \restorecolumns
% \column{body}{l}
% \column{rel}{c}
% \column{rhs}{l}
% \fromto{left}{body}{\qquad\ }
% \fromto{body}{rel}{\HsVar{compare}}
% \fromto{rel}{rhs}{::}
% \fromto{rhs}{end}{\TA\rightarrow\TA\rightarrow\HsCon{Ordering}}
% \nextline
% \fromto{left}{body}{\qquad\ }
% \fromto{body}{rel}{(<),(\leq),(\geq),(>)}
% \fromto{rel}{rhs}{::}
% \fromto{rhs}{end}{\TA\rightarrow\TA\rightarrow\HsCon{Bool}}
% \nextline
% \fromto{left}{body}{\qquad\ }
% \fromto{body}{rel}{\HsVar{max},\HsVar{min}}
% \fromto{rel}{rhs}{::}
% \fromto{rhs}{end}{\TA\rightarrow\TA\rightarrow\HsCon{Bool}}
% \nextline[1ex]
% \fromto{body}{end}{\mbox{--- Minimal complete definition: 
%   $(\leq)$ or $\HsVar{compare}$}}
% \nextline
% \fromto{body}{end}{\mbox{--- using $\HsVar{compare}$ can be more efficient
%   for complex types}}
% \end{pboxed}
% \)
%
% As the comment above says, it is sufficient to define either
% $(\leq)$ or $\HsVar{compare}$ to get a complete instance. All
% of the class methods have default definitions. First, we can
% define $\HsVar{compare}$ in terms of $(\leq)$. The result type
% of $\HsVar{compare}$ is an $\HsCon{Ordering}$, a type consisting
% of only three values: $\HsCon{EQ}$ for ``equality'', 
% $\HsCon{LT}$ for ``less than'', and $\HsCon{GT}$ for ``greater
% than''.
%
% \(
% \begin{pboxed}
% \restorecolumns
% \column{cgrd}{l}
% \fromto{body}{cgrd}{\HsVar{compare}\TX\TY}
% \fromto{cgrd}{rel}{\vert\ \TX\equiv\TY}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\HsCon{EQ}}
% \nextline
% \fromto{cgrd}{rel}{\vert\ \TX\leq\TY}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\HsCon{LT}}
% \nextline
% \fromto{cgrd}{rel}{\vert\ \HsVar{otherwise}}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\HsCon{GT}}
% \end{pboxed}
% \)
%
% All the other comparison operators can be defined
% in terms of $\HsCon{compare}$:
%
% \(
% \begin{pboxed}
% \restorecolumns
% \fromto{body}{rel}{\TX\leq\TY}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\HsVar{compare}\TX\TY\not\equiv\HsCon{GT}}
% \nextline
% \fromto{body}{rel}{\TX < \TY}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\HsVar{compare}\TX\TY\equiv\HsCon{LT}}
% \nextline
% \fromto{body}{rel}{\TX\geq\TY}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\HsVar{compare}\TX\TY\not\equiv\HsCon{LT}}
% \nextline
% \fromto{body}{rel}{\TX > \TY}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\HsVar{compare}\TX\TY\equiv\HsCon{GT}}
% \end{pboxed}
% \)
%
% Finally, there are default definitions for
% $\HsVar{max}$ and $\HsVar{min}$ in terms of $(\leq)$.
%
% \(
% \begin{pboxed}
% \restorecolumns
% \fromto{body}{cgrd}{\HsVar{max}\TX\TY}
% \fromto{cgrd}{rel}{\vert\ \TX\leq\TY}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\TY}
% \nextline
% \fromto{cgrd}{rel}{\vert\ \HsVar{otherwise}}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\TX}
% \nextline
% \fromto{body}{cgrd}{\HsVar{min}\TX\TY}
% \fromto{cgrd}{rel}{\vert\ \TX\leq\TY}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\TX}
% \nextline
% \fromto{cgrd}{rel}{\vert\ \HsVar{otherwise}}
% \fromto{rel}{rhs}{=}
% \fromto{rhs}{end}{\TY}
% \end{pboxed}
% \)
% \hrule
% \caption{Commented Haskell code example}
% \label{tab:saverestore}
% \end{figure}
%
% \section{The Code}
%    \begin{macrocode}
%<*package>
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{polytable}%
   [2004/02/27 v0.7.2 `polytable' package (Andres Loeh)]
%    \end{macrocode}
% New in v0.7.2:
% The \textsf{amsmath} package clashes with \textsf{lazylist}:
% both define the command |\And|. Although it would certainly
% be better to find another name in \textsf{lazylist}, we
% take precautions for now. (Note that this will still fail
% if \textsf{lazylist} is already loaded -- but then it's not
% our problem \dots
%    \begin{macrocode}
\let\PT@original@And\And
\RequirePackage{lazylist}
\let\PT@And\And
\def\PT@prelazylist
  {\let\And\PT@And}
\def\PT@postlazylist
  {\let\And\PT@original@And}
\PT@postlazylist
\RequirePackage{array}
%    \end{macrocode}
%
% The option debug will cause (a considerable amount of)
% debugging output to be printed. The option silent, on
% the other hand, will prevent certain warnings from being
% printed.
%    \begin{macrocode}
\DeclareOption{debug}{\AtEndOfPackage\PT@debug}
\DeclareOption{silent}{\AtEndOfPackage\PT@silent}
\ProcessOptions
%    \end{macrocode}
%
% First, we declare a couple of registers that we will need later.
%    \begin{macrocode}
\newdimen\PT@colwidth
%\newdimen\PT@delta
\newcount\PT@cols
\newcount\PT@table
\newif\ifPT@changed
%    \end{macrocode}
% In |\PT@allcols|, we will store the list of all columns, as a
% list as provided by the \textsf{lazylist} package. We initialise
% it to the empty list, which is represented by |\Nil|. In v0.8,
% we will have a second list that only contains the public columns.
%    \begin{macrocode}
\def\PT@allcols{\Nil}
%\def\PT@allpubliccols{\Nil}
\let\PT@infromto\empty
%    \end{macrocode}
% These are flags and truth values. TODO: Reduce and simplify.
%    \begin{macrocode}
\let\PT@currentwidths\empty
\def\PT@false{0}
\def\PT@true{1}
\let\PT@inrestore\PT@false
%    \end{macrocode}
% The dimension |\PT@delta| is currently not used. The dimension
% comparisons should probably have a small tolerance, to prevent
% infinite loops due to rounding errors. (Can this really happen?)
%    \begin{macrocode}
%\PT@delta\hfuzz
%    \end{macrocode}
% 
% \begin{macro}{\PT@debug}
% \begin{macro}{\PT@typeout@}
% \begin{macro}{\PT@silent}
% \begin{macro}{\PT@warning}
% Similar to the \textsf{tabularx} package, we add macros to
% print debugging information to the log. Depending on package
% options, we can set or unset them.
%    \begin{macrocode}
\def\PT@debug
  {\def\PT@typeout@ ##1{\typeout{(polytable) ##1}}}
\let\PT@typeout@\@gobble
\def\PT@warning{\PackageWarning{polytable}}%
\def\PT@silent
  {\let\PT@typeout@\@gobble\let\PT@warning\@gobble}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\PT@rerun}
% This macro can be called at a position where we know that
% we have to rerun LaTeX to get the column widths right. It
% issues a warning at the end of the document.
%    \begin{macrocode}
\def\PT@rerun
  {\PT@typeout@{We have to rerun LaTeX ...}%
   \AtEndDocument
     {\PackageWarning{polytable}%
        {Column widths have changed. Rerun LaTeX.\@gobbletwo}}%
   \global\let\PT@rerun\relax}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Macro definition tools}
%
% \begin{macro}{\PT@listopmacro}
% \begin{macro}{\PT@consmacro}
% \begin{macro}{\PT@appendmacro}
% This assumes that |#2| is a list macro and |#3| is a new list element.
% The macro |#2| should, after the call, expand to the list with the
% new element |#1|ed. Because we don't know the number of tokens in |#3|,
% we use a temporary macro |\PT@temp| (which is used frequently throughout
% the package).
%    \begin{macrocode}
\def\PT@listopmacro #1#2#3% #1 #3 to the list #2
  {\def\PT@temp{#1{#3}}%
   \expandafter\expandafter\expandafter
     \def\expandafter\expandafter\expandafter 
     #2\expandafter\expandafter\expandafter
     {\expandafter\PT@temp\expandafter{#2}}}

\def\PT@consmacro{\PT@listopmacro\Cons}
\def\PT@appendmacro{\PT@listopmacro\Cat}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% The follwing two macros can be used to add something to
% the beginning or the end of a constrol structure.
%    \begin{macrocode}
\def\PT@addbeginmacro #1#2% add #2 to the beginning of #1
  {\def\PT@temp{#2}%
   \expandafter\expandafter\expandafter
     \def\expandafter\expandafter\expandafter 
     #1\expandafter\expandafter\expandafter
     {\expandafter\PT@temp #1}}

\def\PT@gaddendmacro #1#2% add #2 to the end of #1
  {\expandafter\gdef\expandafter #1\expandafter{#1#2}}
%    \end{macrocode}
% \begin{macro}{\PT@enamedef}
% This is much like |\@namedef|, but it expands |#2| once.
%    \begin{macrocode}
\def\PT@enamedef #1#2% sets name #1 to the expansion of #2
  {\expandafter\Twiddle\expandafter\@namedef\expandafter{#2}{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@adddeftomacroas}
% Given the name of a control structure |#1| and a name of another
% control structure |#2| and an expression |#3|, we add the
% definition of |#2| to the expansion of |#3| to the macro |#1|.
%    \begin{macrocode}
\def\PT@adddeftomacroas#1#2#3%
  {\expandafter\expandafter\expandafter
     \def\expandafter\expandafter\expandafter\PT@temp
       \expandafter\expandafter\expandafter
         {\expandafter\expandafter\expandafter\def
            \expandafter\expandafter\csname #2\endcsname
            \expandafter{#3}}%
   \expandafter\expandafter\expandafter\PT@gaddendmacro
     \expandafter\expandafter\expandafter
       {\expandafter\expandafter\csname #1\endcsname
        \expandafter}\expandafter{\PT@temp}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@adddeftomacro}
% This is a special case of |\PT@adddeftomacroas| where |#3| is
% the expansion of |#2|.
%    \begin{macrocode}
\def\PT@adddeftomacro#1#2%
  {\def\PT@temp{\PT@adddeftomacroas{#1}{#2}}%
   \expandafter\PT@temp\csname #2\endcsname}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@addoptargtomacro}
%    \begin{macrocode}
\def\PT@addoptargtomacro
  {\PT@add@argtomacro\PT@makeoptarg}
\def\PT@addargtomacro
  {\PT@add@argtomacro\PT@makearg}

\def\PT@add@argtomacro#1#2#3%
  {\expandafter\expandafter\expandafter\gdef
     \expandafter\expandafter\expandafter\PT@temp
       \expandafter\expandafter\expandafter{\csname #3\endcsname}%
   #1%
   \expandafter\PT@gaddendmacro\expandafter
     {\expandafter#2\expandafter}\expandafter{\PT@temp}}

\def\PT@makeoptarg%
  {\expandafter\def\expandafter\PT@temp\expandafter
     {\expandafter[\PT@temp]}}
\def\PT@makearg%
  {\expandafter\def\expandafter\PT@temp\expandafter
     {\expandafter{\PT@temp}}}

%
% \begin{macro}{\PT@mtimesn}
% Expands to |#1| times |#2|. (Work in progress.)
%    \begin{macrocode}
% \def\PT@mtimesn #1#2%
%   {\expandafter\PT@mtimtesn@\romannumeral #1011{#2}}
% \def\PT@mtimesn@ #1i#2%
%   {\if#1m%
%      #2\expandafter\PT@mtimesn@#1i#3}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@gobbleoptional}
% Gobbles one optional argument. Ignores spaces.
%    \begin{macrocode}
\newcommand*{\PT@gobbleoptional}[1][]{\ignorespaces}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@origomit}
% Save the original definition of omit.
%    \begin{macrocode}
\let\PT@origomit\omit
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\PT@disableomitonce}
% Undefines the next use of omit.
%    \begin{macrocode}
\def\PT@disableomitonce
  {\def\omit
     {\let\omit\PT@origomit}}
%    \end{macrocode}
% \end{macro}
%
% \subsection{The environment}
%
% The general idea is to first scan the contents of the environment
% and store them in a token register. In a few test runs, the positions
% of the column borders are determined. After that, the columns are sorted
% and the table is typeset, translating the named ranges into appropriate
% calls to |\multicolumn|.
%
% \begin{macro}{\beginpolytable}
% This macro starts the environment. It should, however, not
% be called directly, but rather in a \LaTeX\ environment.
% We just initialize the
% token register to the empty string and then start scanning.
%    \begin{macrocode}
\newcommand{\beginpolytable}%
%    \end{macrocode}
% We save the current enclosing \LaTeX\ environment in
% |\PT@environment|. This will be the |\end| we will be
% looking for, and this will be the environment we manually
% close in the end.
%    \begin{macrocode}
  {\edef\PT@environment{\@currenvir}%
   \begingroup
   % new in v0.7: save counters
   \PT@savecounters
   \toks@{}% initialise token register
   \PT@scantoend}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\endpolytable}
% This is just defined for convenience.
%    \begin{macrocode}
\let\endpolytable=\relax
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\PT@scantoend}
% We scan until the next occurence of |\endpolytable| and
% store the tokens. Then we continue with determining the
% column widths.
%    \begin{macrocode}
\long\def\PT@scantoend #1\end #2%
  {\toks@\expandafter{\the\toks@ #1}%
   \def\PT@temp{#2}%
   \ifx\PT@temp\PT@environment
     \expandafter\PT@getwidths
   \else
     \toks@\expandafter{\the\toks@\end{#2}}%
     \expandafter\PT@scantoend
   \fi}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\PT@getwidths}
% Here, we make as many test runs as are necessary to 
% determine the correct column widths.
%    \begin{macrocode}
\def\PT@getwidths
%    \end{macrocode}
% We let the |\column| command initialize a column
% in the first run.
%    \begin{macrocode}
  {\let\column\PT@firstrun@column
%    \end{macrocode}
% There is the possibility to save or restore columns.
% This is new in v0.4.
%    \begin{macrocode}
   \let\savecolumns\PT@savewidths
   \let\restorecolumns\PT@restorewidths
%    \end{macrocode}
% We \emph{always} define a pseudo-column |@begin@|.
% This denotes the begin of a row.
%    \begin{macrocode}
   \column{@begin@}{@{}l@{}}
   \PT@cols=0\relax%
%    \end{macrocode}
% The two other commands that are allowed inside of the
% environment, namely |\fromto| and |\nextline| are
% initialized. The |\fromto| command may increase the
% current widths of some columns, if necessary, whereas
% |\nextline| just resets the counter that keeps track
% of the ``current'' column, to |0|.
%    \begin{macrocode}
   \let\fromto\PT@fromto
   \let\nextline\PT@resetcolumn
   \PT@changedfalse % nothing has changed so far
   \PT@resetcolumn % we are at the beginning of a line
%    \end{macrocode}
% Now we are ready for a test run.
%    \begin{macrocode}
   \the\toks@
%    \end{macrocode}
% After the first run, we print extra information.
% We use the contents of the macro |\column| to check
% whether we are in the first run, because it will be
% reset below for all other runs to do nothing.   
%    \begin{macrocode}
   \ifx\column\PT@otherrun@column
   \else
      % we are in first run, print extra info
      \PT@typeout@{Number of columns: \the\PT@cols}%
      \PT@prelazylist
      \PT@typeout@{Column list: \Print\PT@allcols}%
      \PT@postlazylist
   \fi
%    \end{macrocode}
% The columns are initialised after the first run.
% Therefore, we make sure that the |\column| command
% won't do much in the other runs. Also, saving and
% restoring columns is no longer needed.
%    \begin{macrocode}
   \let\PT@firstrun@column\PT@otherrun@column
   \let\savecolumns\PT@gobbleoptional
   \let\restorecolumns\PT@gobbleoptional
   \let\PT@savewidths\PT@gobbleoptional
   \let\PT@restorewidths\PT@gobbleoptional
%    \end{macrocode}
% New in v0.7.1: restore counters after each trial run.
%    \begin{macrocode}
   \PT@restorecounters
%    \end{macrocode}
% If some column widths have indeed changed in the
% test run, this will be indicated by the flag
% |\ifPT@changed|. Depending on this flag, we will
% either loop and rerun, or we will continue in
% |\PT@sortcols|.
%    \begin{macrocode}
   \ifPT@changed
      % we need to rerun if something has changed
      \expandafter\PT@getwidths
   \else
      % we are done and can do the sorting
      \PT@typeout@{Reached fixpoint.}%
      \expandafter\PT@sortcols
   \fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@savecounters}
% Save all \LaTeX\ counters so that they can be restored after a
% trial run.
%    \begin{macrocode}
\def\PT@savecounters
  {\begingroup
      \def\@elt ##1%
        {\global\csname c@##1\endcsname\the\csname c@##1\endcsname}%
      \xdef\PT@restorecounters{\cl@@ckpt}%
   \endgroup}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@sortcols}
% The column borders are sorted by their horizontal
% position on the page (width). The they get numbered
% consecutively. After that, we are well prepared to
% typeset the table.
%    \begin{macrocode}
\def\PT@sortcols
%    \end{macrocode}
% First, we sort the list. To make sure that the
% computation is only executed once, we save the
% sorted list by means of an |\edef|. Sorting happens
% with \textsf{lazylist}'s |\Insertsort| which expects
% an order and a list. As order, we provide |\PT@ltwidth|,
% which compares the widths of the columns.
% To prevent expansion of the list structure, given by
% |\Cons| and |\Nil|, we fold the list with the
% |\noexpand|ed versions of the list constructors.
%    \begin{macrocode}
  {\PT@prelazylist
   \edef\PT@sortedlist
     {\Foldr{\noexpand\Cons}{\noexpand\Nil}%
        {\Insertsort\PT@ltmax\PT@allcols}}%
   \PT@typeout@{Sorted columns: \Print\PT@sortedlist}%
   \PT@postlazylist
%    \end{macrocode}
% Now, each column is assigned a number, starting from
% zero.
%    \begin{macrocode}
   \PT@cols=0\relax%
   \PT@prelazylist
   \Execute{\Map\PT@numbercol\PT@sortedlist}%
   \PT@postlazylist
   \PT@typeout@{Numbered successfully, last column is \StripColumn\PT@lastcol}%
%    \end{macrocode}
% Now is a good time to save table information, if needed later.
% We will also compare our computed information with the restored
% maximum widths.
%    \begin{macrocode}
      \ifx\PT@currentwidths\empty
      \else
         \PT@typeout@{Saving table information for \PT@currentwidths .}%
         \expandafter\PT@saveinformation\expandafter{\PT@currentwidths}%
      \fi
%    \end{macrocode}
% Finally, we can typeset the table.
%    \begin{macrocode}
   \PT@typeset}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\PT@typeset}
%    \begin{macrocode}
\def\PT@typeset
%    \end{macrocode}
% As a first step, we generate the table's preamble and
% print it for debugging purposes.
%    \begin{macrocode}
  {\PT@typeout@{Typesetting the table ...}%
   \PT@prelazylist
   \edef\PT@temp{@{}\Execute{\Map\PT@preamble\PT@sortedlist}}%
   \PT@postlazylist
   %\PT@typeout@{Preamble: \PT@temp}%
%    \end{macrocode}
% Now, we redefine |\fromto| and |\nextline| to their
% final meaning in the typesetting process. The
% |\fromto| statements will be replaced by appropriate
% calls to |\multicolumn|, whereas the |\nextline| will
% again reset the counter for the current column, but
% also call the table environment's newline macro.
%    \begin{macrocode}
   \let\fromto\PT@multicolumn
   \PT@resetcolumn % we are at the beginning of a line
   \let\nextline=\PT@resetandcr
%    \end{macrocode}
% Now we start the tabular environment with the
% computed preamble.
%    \begin{macrocode}
   \expandafter\PT@begin\expandafter{\PT@temp}%
%    \end{macrocode}
% Run, and this time, typeset, the contents.
%    \begin{macrocode}
   \the\toks@
%    \end{macrocode}
% End the array, close the group, close the environment. 
% We are done!
%    \begin{macrocode}
   \PT@end
   \endgroup
   \PT@typeout@{Finished.}%
   \expandafter\end\expandafter{\PT@environment}}%
%    \end{macrocode}
% \end{macro}
%
% \subsection{The trial runs}
%
% For each column, we store information in macros that are
% based on the column name. We store a column's type (i.e.~its
% contribution to the table's preamble), its current width
% (i.e.~its the horizontal position where the column will start
% on the page), and later, its number, which will be used for
% the |\multicolumn| calculations.
%
% \begin{macro}{\PT@firstrun@column}
% During the first trial run, we initialise all the columns. We
% store their type, as declared in the |\column| command inside
% the environment, and we set their initial width to 0pt.
% Furthermore, we add the column to the list of all available
% columns, increase the column counter, and tell \TeX\ to ignore
% spaces that might follow the |\column| command.
% New in v0.4.1: We make a case distinction on an empty type
% field to prevent warnings for columns that have been defined
% via |\PT@setmaxwidth| -- see there for additional comments.
% New in v0.4.2: We allow redefinition of width if explicitly
% specified, i.e. not equal to 0pt.
%    \begin{macrocode}
\newcommand\PT@firstrun@column[3][0pt]%
  {\@ifundefined{PT@col@#2.type}%
      {\PT@typeout@{Defining column #2 at #1.}%
       \@namedef{PT@col@#2.type}{#3}%
       \@namedef{PT@col@#2.width}{#1}% initialize the width of the column
       % add the new column to the (sortable) list of all columns
       \PT@consmacro\PT@allcols{PT@col@#2}%
       \advance\PT@cols by 1\relax}%
      {\expandafter\ifx\csname PT@col@#2.type\endcsname\empty
         \relax % will be defined in a later table of the same set
       \else
         \PT@warning{Redefining column #2}%
       \fi
       \@namedef{PT@col@#2.type}{#3}%
       \expandafter\ifdim#1>0pt\relax
         \PT@typeout@{Redefining column #2 at #1.}%
         \@namedef{PT@col@#2.width}{#1}%
       \fi
      }%
%    \end{macrocode}
% For the case that we are saving and there is not yet information
% from the |.aux| file, we define the |.max| and |.trusted| fields
% if they are undefined. If information becomes available later, it
% will overwrite these definitions.
%    \begin{macrocode}
   \@ifundefined{PT@col@#2.max}%
      {\@namedef{PT@col@#2.max}{#1}%
       \expandafter\let\csname PT@col@#2.trusted\endcsname\PT@true}{}%  
   \ignorespaces}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\PT@otherrun@column}
% In all but the first trial run, we do not need any additional
% information about the columns any more, so we just gobble the
% two arguments, but still ignore spaces.
%    \begin{macrocode}
\newcommand\PT@otherrun@column[3][]%
  {\ignorespaces}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\PT@checkcoldefined}
% This macro verifies that a certain column is defined and
% produces an error message if it is not.
%    \begin{macrocode}
\def\PT@checkcoldefined #1%
  {\@ifundefined{PT@col@#1.type}%
      {\PackageError{polytable}{Undefined column #1}{}}{}}%
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\PT@fromto}
% Most of the work during the trial runs is done here. We increase
% the widths of certain columns, if necessary. Note that there
% are two conditions that have to hold if |\fromto{A}{B}| is encountered:
% \begin{itemize}
% \item the width of |A| has to be at least the width of the current
%    (i.e.~previous) column.
% \item the width of |B| has to be at least the width of |A|, plus the
%    width of the entry.
% \end{itemize}
%    \begin{macrocode}
\def\PT@fromto #1#2#3%
%    \end{macrocode}
% We start by checking a switch.
%    \begin{macrocode}
  {\PT@infromto
   \def\PT@infromto{%
     \PackageError{polytable}{Nested fromto}{}}%
%    \end{macrocode}
% Next, we check that both columns are defined.
%    \begin{macrocode}
   \PT@checkcoldefined{#1}%
   \PT@checkcoldefined{#2}%   
%    \end{macrocode}
% Here, we check the first condition.
%    \begin{macrocode}
   \def\PT@temp{PT@col@#1}%
   \ifx\PT@currentcol\PT@temp
     \PT@typeout@{No need to skip columns.}%
   \else
     \PT@colwidth=\expandafter\@nameuse\expandafter
                    {\PT@currentcol.width}\relax
     \ifdim\PT@colwidth>\csname PT@col@#1.width\endcsname\relax
       % we need to change the width
       \PT@typeout@{s #1: old=\@nameuse{PT@col@#1.width} new=\the\PT@colwidth}%
       \PT@changedtrue
       \PT@enamedef{PT@col@#1.width}{\the\PT@colwidth}%
     \fi
%    \end{macrocode}
% The same for the untrusted |.max| values.
%    \begin{macrocode}
     \PT@colwidth=\expandafter\@nameuse\expandafter
                    {\PT@currentcol.max}\relax
     \ifdim\PT@colwidth>\csname PT@col@#1.max\endcsname\relax
       % we need to change the width
       \PT@typeout@{S #1: old=\@nameuse{PT@col@#1.max} new=\the\PT@colwidth}%
       \PT@changedtrue
       \PT@checkrerun
       \PT@enamedef{PT@col@#1.max}{\the\PT@colwidth}%
     \fi
     \ifnum\csname PT@col@#1.trusted\endcsname=\PT@false\relax
       \ifdim\PT@colwidth=\csname PT@col@#1.max\endcsname\relax
         \PT@typeout@{#1=\the\PT@colwidth\space is now trusted}%
         \expandafter\let\csname PT@col@#1.trusted\endcsname\PT@true%
       \fi
     \fi
   \fi
%    \end{macrocode}
% To test the second condition, we have to test-typeset the contents of
% the column, contained in |#3|. We prepare a ``safe environment'' for these
% contents. We determine whether we are in math mode
% or not, put the contents into an hbox in the same mode, and we are
% typesetting the contents in the same environment as we will typeset the
% table in the end. 
%    \begin{macrocode}
   \begingroup
   \ifmmode
     \let\d@llarbegin=$%$
     \let\d@llarend=$%$
     \let\col@sep=\arraycolsep
   \else
     \let\d@llarbegin=\begingroup
     \let\d@llarend=\endgroup
     \let\col@sep=\tabcolsep
   \fi
   %\def\PT@currentcol{PT@col@#1}%
   %\ifx\PT@currentcol\PT@nullcol
   %\else
   %  \PT@addbeginmacro\PT@currentpreamble{@{}}%
   %\fi
   \expandafter\expandafter\expandafter
     \def\expandafter\expandafter\expandafter\PT@currentpreamble
       \expandafter\expandafter\expandafter
         {\csname PT@col@#1.type\endcsname}%
   \setbox0=\hbox{%
     \expandafter\@mkpream\expandafter{\PT@currentpreamble}%
     \def\@sharp{\strut #3}%
     %\show\@preamble
     \@preamble}%
   \expandafter\gdef\expandafter\PT@temp\expandafter{\the\wd0}%
   \endgroup
%    \end{macrocode}
% Now begins the real comparison.
%    \begin{macrocode}
   \global\PT@colwidth=\@nameuse{PT@col@#1.width}%
   \global\advance\PT@colwidth by \PT@temp\relax%
   \ifdim\PT@colwidth>\csname PT@col@#2.width\endcsname\relax
     % we need to change the width
     \PT@typeout@{c #2: 
                  old=\@nameuse{PT@col@#2.width} 
                  new=\the\PT@colwidth}%
     \PT@changedtrue
     \PT@enamedef{PT@col@#2.width}{\the\PT@colwidth}%
   \fi
%    \end{macrocode}
% And again, we have to do the same for the untrusted maximums.
%    \begin{macrocode}
   \global\PT@colwidth=\@nameuse{PT@col@#1.max}%
   \global\advance\PT@colwidth by \PT@temp\relax%
   \ifdim\PT@colwidth>\csname PT@col@#2.max\endcsname\relax
     % we need to change the width
     \PT@typeout@{C #2: 
                  old=\@nameuse{PT@col@#2.max} 
                  new=\the\PT@colwidth}%
     \PT@changedtrue
     \PT@checkrerun
     \PT@enamedef{PT@col@#2.max}{\the\PT@colwidth}%
   \fi
   \ifnum\csname PT@col@#2.trusted\endcsname=\PT@false\relax
     \ifdim\PT@colwidth=\csname PT@col@#2.max\endcsname\relax
       \PT@typeout@{#2=\the\PT@colwidth\space is now trusted}%
       \expandafter\let\csname PT@col@#2.trusted\endcsname\PT@true%
     \fi
   \fi
%    \end{macrocode}
% Finally, we update the current column to |#2|, and, of course, we
% ignore spaces after the |\fromto| command.
%    \begin{macrocode}
   \def\PT@currentcol{PT@col@#2}%
   \let\PT@infromto\empty
   \ignorespaces}%
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\PT@checkrerun}
% If we have changed something with the trusted widths, we have
% to check whether we are in a situation where we are using previously
% defined columns. If so, we have to rerun \LaTeX.
%    \begin{macrocode}
\def\PT@checkrerun
  {\ifnum\PT@inrestore=\PT@true\relax
     \PT@rerun
   \fi}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\PT@resetcolumn}
% At the end of a line, we reset the current column to the special
% column |@begin@|. 
%    \begin{macrocode}
\newcommand*{\PT@resetcolumn}[1][]%
  {\let\PT@currentcol\PT@nullcol}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\PT@nullcol}
% The name of the |@begin@| column as a macro, to be able to compare
% to it with |\ifx|.
%    \begin{macrocode}
\def\PT@nullcol
  {PT@col@@begin@}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Sorting and numbering the columns}
%
% Not much needs to be done here, all the work is done by the
% macros supplied by the \textsf{lazylist} package.
% We just provide a few additional commands to facilitate
% their use.
%
% \begin{macro}{\Execute}
% \begin{macro}{\Sequence}
% With |\Execute|, a list of commands (with sideeffects) can
% be executed in sequence. Usually, first a command will be
% mapped over a list, and then the resulting list will be
% executed.
%    \begin{macrocode}
\def\Execute{\Foldr\Sequence\empty}
\def\Sequence #1#2{#1#2}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\ShowColumn}
% This is a debugging macro, that is used to output the list
% of columns in a pretty way. The columns internally get
% prefixes to their names, to prevent name conflicts with
% normal commands. In the debug output, we gobble this prefix
% again.
%    \begin{macrocode}
\def\ShowColumn #1%
  {\ShowColumn@#1\ShowColumn@}
\def\ShowColumn@ PT@col@#1\ShowColumn@
  {#1 }
\def\StripColumn #1%
  {\expandafter\StripColumn@#1\StripColumn@}
\def\StripColumn@ PT@col@#1\StripColumn@
  {#1}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\Print}
% Prints a list of columns, using |\ShowColumn|.
%    \begin{macrocode}
\def\Print#1{\Execute{\Map\ShowColumn#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@TeXif}
% This is an improved version of \textsf{lazylist}'s |\TeXif|. 
% It does have an additional |\relax| to terminate the condition.
% The |\relax| is gobbled again to keep it fully expandable.
%    \begin{macrocode}
\def\PT@TeXif #1%
  {\expandafter\@gobble#1\relax
     \PT@gobblefalse
   \else\relax
     \gobbletrue
   \fi}
\def\PT@gobblefalse\else\relax\gobbletrue\fi #1#2%
  {\fi #1}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@ltmax}
% The order by which the columns are sorted is given by
% the order on their (untrusted) widths.
%    \begin{macrocode}
\def\PT@ltmax #1#2%
  {\PT@TeXif{\ifdim\csname #1.max\endcsname<\csname #2.max\endcsname}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@numbercol}
% This assigns the next consecutive number to a column.
% We also reassign |PT@lastcol| to remember the final column.
%    \begin{macrocode}
\def\PT@numbercol #1%
  {%\PT@typeout@{numbering #1 as \the\PT@cols}%
   \PT@enamedef{#1.num}{\the\PT@cols}%
   \def\PT@lastcol{#1}%
   \advance\PT@cols by 1\relax}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Typesetting the table}
%
% \begin{macro}{\PT@preamble}
% The table's preamble is created by mapping this function
% over the column list and then |\Execute|ing \dots
% New: We always use |l|, as the specific type is always
% given by the |\multicolumn|.
% Yet new: We use |@{}l@{}|, to prevent column separation
% space from being generated.
%    \begin{macrocode}
\def\PT@preamble #1%
%  {\csname #1.type\endcsname}
%  {l}
   {l@{}}
%    \end{macrocode}
% \end{macro}
%
% Remember that there are three important macros that
% occur in the body of the polytable: |\column|, |\fromto|,
% and |\nextline|. The |\column| macro is only really used
% in the very first trial run, so there is nothing new
% we have to do here, but the other two have to be
% redefined.
%
% \begin{macro}{\PT@resetandcr}
% This is what |\nextline| does in the typesetting phase.
% It resets the current column, but it also calls the table
% environment's newline macro |\\| \dots
% If we are \emph{not} in the last column, we insert
% an implicit |fromto|. This is needed for the boxed environment to
% make each column equally wide. Otherwise, if the boxed environment
% is typeset in a centered way, things will go wrong.
%    \begin{macrocode}
\newcommand{\PT@resetandcr}[1][0pt]%
  {\ifx\PT@currentcol\PT@lastcol
   \else
     \ifx\PT@currentcol\PT@nullcol
       \edef\PT@currentcol{\Head{\Tail\PT@sortedlist}}%
     \fi
     \edef\PT@currentcol@{\StripColumn\PT@currentcol}%
     \edef\PT@lastcol@
       {\StripColumn\PT@lastcol}%
     \PT@typeout@{adding implicit fromto from \PT@currentcol@ 
                                  \space to \PT@lastcol@}%
     \expandafter\expandafter\expandafter\fromto
       \expandafter\expandafter\expandafter{%
         \expandafter\expandafter\expandafter\PT@currentcol@
           \expandafter}\expandafter{\PT@lastcol@}{}%
   \fi
   \PT@typeout@{Next line ...}%
   \PT@resetcolumn\\[#1]}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@multicolumn}
% All the |\fromto|s are expanded into |\multicolumn| calls,
% which is achieved by this quite tricky macro. Part of the
% trickyness stems from the fact that a |\multicolumn|'s
% expansion starts with |\omit| which is a plain \TeX\ primitive
% that causes the template for a table column to be ignored.
% But |\omit| has to be the first token (after expansion)
% in a column to be valid, which is why the alignment tabs |&|
% and the |\multicolumn| calls have to be close to each other.
% It would maybe be better to call |\omit| manually and hack
% |\multicolumn| later!!
%
% This macro gets three arguments. The first is the column
% in which the entry begins, the second is the column
% \emph{before} which the entry stops, and the third contains
% the contents that should be typeset in this range.
%    \begin{macrocode}
\def\PT@multicolumn #1#2#3%
%    \end{macrocode}
% We start by producing an |\omit| to indicate that we want
% to ignore the column format that has been specified in the
% table header. After that, we disable the |\omit| command,
% because we will later call |\multicolumn| which contains
% another one. A second |\omit| would usually cause an error.
% TODO: Make this work to simplify the rest. For now, we don't
% use this.
%    \begin{macrocode}
  {%\omit\PT@disableomitonce
%    \end{macrocode}
% We skip ahead until we are in the column in which the entry
% should start. For this, we store the
% number of the column we want to start in and subtract
% the current columns number. If the current column is the
% null column, we have to adjust by $-1$ which is not nice,
% but necessary \dots
% In 0.4.3: added missing relax after |\global\advance|.
%    \begin{macrocode}
   % skip to current position
   \global\PT@cols=\@nameuse{PT@col@#1.num}%
   \global\advance\PT@cols 
     by -\expandafter\csname\PT@currentcol.num\endcsname\relax
   \ifx\PT@currentcol\PT@nullcol
     \global\advance\PT@cols by -1\relax%
   \fi
%    \end{macrocode}
% We now skip by inserting alignment tabs and using a
% multicolumn with no content. It might be nicer to just
% use as many tabs as necessary, because we could do with
% less case distinctions. The current value of |\PT@cols|
% indicates how many tabs we have to insert, minus one.
% We will insert that one tab (which is the minimum we have
% to insert) just before we insert the content, and first
% deal with the extra tabs.
%    \begin{macrocode}
   \PT@typeout@{skipping:
                nf=\expandafter\ShowColumn
                     \expandafter{\PT@currentcol}nt=#1 %
                from=\expandafter
                       \csname\PT@currentcol.num\endcsname\space
                to=\@nameuse{PT@col@#1.num}}%
   \ifnum\PT@cols>0\relax
%    \end{macrocode}
% So there are extra tabs necessary.
%    \begin{macrocode}
     \ifnum\PT@cols>1\relax
%    \end{macrocode}
% We can use a multicolumn to save time.
%    \begin{macrocode}
       \global\advance\PT@cols by -1\relax
       \PT@typeout@{after next &, multicolumn \the\PT@cols\space blank}%
       \PT@NextCol
       \multicolumn{\the\PT@cols}{@{}l@{}}{}%
     \fi
     \PT@NextCol
   \fi
%    \end{macrocode}
% We now are in the correct column and can print the contents. Again,
% we have to check if we have to use a |\multicolumn|. If we do, we will
% use the formatting type of the first column that it spans, in contrast
% to normal |\multicolumn|s which always take an extra parameter to
% determine how to format their contents. An optional parameter should
% be introduced here to make overriding the default template possible!!
% New: we always use a |\multicolumn|, otherwise spacing will be
% inconsistent sometimes.
%    \begin{macrocode}
   \global\PT@cols=\@nameuse{PT@col@#2.num}%
   \global\advance\PT@cols by -\@nameuse{PT@col@#1.num}\relax%
   %\ifnum\PT@cols>1\relax
      % we always skip one column
      \PT@typeout@{after next &, 
                   putting text in \the\PT@cols\space multicol}%
      \PT@typeout@{nf=#1 nt=#2 %
                   from=\@nameuse{PT@col@#1.num} 
                   to=\@nameuse{PT@col@#2.num}}%
      \expandafter\global\expandafter\let\expandafter\PT@temp
        \csname PT@col@#1.type\endcsname%
      \PT@NextCol
      % use multicolumn
      \expandafter\multicolumn
        \expandafter{\expandafter\the\expandafter\PT@cols
        \expandafter}\expandafter{\PT@temp}{#3}%
      %\PT@typeout@{!!!!}%
   %\else
   %   \PT@NextCol
   %   #3%
   %\fi
%    \end{macrocode}
% We reset the current column to |#2| and ignore spaces after
% the command. Then we are done \dots
%    \begin{macrocode}
   % set current column
   \def\PT@currentcol{PT@col@#2}%
   \ignorespaces}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@NextCol}
% We hide the tab |&| in a macro, mostly to be able to
% add debugging output.
%    \begin{macrocode}
\def\PT@NextCol
  {\PT@typeout@{ & }%
   &}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@placeinbox}
% This macro is an alternative for |\PT@multicolumn|. It can be used
% to produce a simple box-based output instead of a table. We use
% the precomputed width information to typeset the contents of the
% table in aligned boxes. The arguments are the same as for
% |\PT@multicolumn|, i.e.~the start and the end columns, plus the contents.
%    \begin{macrocode}
\def\PT@placeinbox#1#2#3%
%    \end{macrocode}
% We start by computing the amount of whitespace that
% must be inserted before the entry begins. We then insert that amount
% of space.
%    \begin{macrocode}
  {\PT@colwidth=\@nameuse{PT@col@#1.max}%
   \advance\PT@colwidth by -\expandafter\csname\PT@currentcol.max\endcsname
   \leavevmode
   \hb@xt@\PT@colwidth{%
     \expandafter\@mkpream\expandafter{@{}l@{}}%
     \let\@sharp\empty%
     %\show\@preamble
     \@preamble}%
% We continue by computing the width of the current entry.
%    \begin{macrocode}
   \PT@colwidth=\@nameuse{PT@col@#2.max}%
   \advance\PT@colwidth by -\@nameuse{PT@col@#1.max}\relax%
%    \end{macrocode}
% In the previous version, we really generated a hbox at this place.
% However, this is not so nice with respect to spacing and tabular
% specifiers. Therefore, we now use either an array or a tabular
% environment that can reuse the given specifier.
%    \begin{macrocode}
   \ifmmode
     \PT@typeout@{*math mode*}%
     \let\d@llarbegin=$%$
     \let\d@llarend=$%$
     \let\col@sep=\arraycolsep
   \else
     \PT@typeout@{*text mode*}%
     \let\d@llarbegin=\begingroup
     \let\d@llarend=\endgroup
     \let\col@sep=\tabcolsep
   \fi
   %\def\PT@currentcol{PT@col@#1}%
   \expandafter\expandafter\expandafter
     \def\expandafter\expandafter\expandafter\PT@currentpreamble
       \expandafter\expandafter\expandafter
         {\csname PT@col@#1.type\endcsname}%
   %\ifx\PT@currentcol\PT@nullcol
   %\else
   %  \PT@addbeginmacro\PT@currentpreamble{@{}}%
   %\fi
%    \end{macrocode}
% Now we proceed very much like in the test run(s), but we
% really output the box, and we use a specific width.
%    \begin{macrocode}
   \hb@xt@\PT@colwidth{%
     \expandafter\@mkpream\expandafter{\PT@currentpreamble}%
     \def\@sharp{\strut #3}%
     %\show\@preamble
     \@preamble}%
%    \end{macrocode}
% Finally, we have to reset the current column and
% ignore spaces.
%    \begin{macrocode}
   \def\PT@currentcol{PT@col@#2}%
   \ignorespaces}%
%    \end{macrocode}
% \end{macro}
%
% \subsection{Saving and restoring column widths}
%
% Column width information can be saved under a name and thus
% be reused in other tables. The idea is that the command
% |\savecolumns| can be issued inside a polytable to save the
% current column information, and |\restorecolumns| can be used
% to make that information accessible in a later table. All tables
% using the same information should have the same column widths,
% which means that some information might need to be passed back.
% Therefore, we need to write to an auxiliary file.
% TODO: As implemented now, this only really works in conjunction
% with the |pboxed| environment.
%
% Both |\savecolumns| and |\restorecolumns| are mapped to the internal
% commands |\PT@savewidths| and |\PT@restorewidths|. Both take an
% optional argument specifying a name for the column width
% information. Thereby, multiple sets of such information can be
% used simultaneously.
%
% One important thing to consider is that the widths read from the
% auxiliary file must not be trusted. The user may have edited the
% source file before the rerun, and therefore, the values read might
% actually be too large (or too small, but this is less dangerous).
%
% The way we solve this problem is to distinguish two width values
% per column: the trusted width, only using information from the
% current run, and the untrusted width, incorportating information
% from the |.aux| file. An untrusted width can become (conditionally)
% trusted if it is reached in the computation with respect to an
% earlier column. (Conditionally, because its trustworthiness still
% depends on the earlier columns being trustworthy.) In the end, we
% can check whether all untrusted widths are conditionally trusted.
%
% We write the final, the maximum widths, into the auxiliary file.
% We perform the 
% write operation when we are sure that a specific set is
% no longer used. This is the case when we save a new set under the
% same name, or at the end of the document. The command 
% |\PT@verifywidths| takes care of this procedure.
% This command will also check if a rerun is necessary, and issue
% an appropriate warning if that should be the case.
%
% \begin{macro}{\PT@setmaxwidth}
% First, we need a macro to help us interpreting the contents of
% the |.aux| file. New v0.4.1: We need to define the restored
% columns with the |\column| command, because otherwise we will
% have problems in the case that later occurences of tables in
% the document that belong to the same set, but define additional
% columns. (Rerun warnings appear ad infinitum.)
% In v0.4.2: columns with width 0.0 are now always trusted.
%    \begin{macrocode}
\newcommand*{\PT@setmaxwidth}[3][\PT@false]% #2 column name, #3 maximum width
  {\@namedef{PT@col@#2.max}{#3}%
   \ifdim#3=0pt\relax
     \expandafter\let\csname PT@col@#2.trusted\endcsname=\PT@true%
   \else
     \expandafter\let\csname PT@col@#2.trusted\endcsname=#1%
   \fi
   \column{#2}{}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@loadtable}
% Now, we can load table information that has been read from the
% |.aux| file. Note that a |\csname| construct expands to |\relax|
% if undefined.
%    \begin{macrocode}
\def\PT@loadtable#1% #1 table id number
  {%\expandafter\show\csname PT@restore@\romannumeral #1\endcsname
   %\show\column
   \PT@typeout@
     {Calling \expandafter\string
                \csname PT@restore@\romannumeral #1\endcsname.}%
   \let\maxcolumn\PT@setmaxwidth
   %\expandafter\show\csname PT@load@\romannumeral #1\endcsname
   \csname PT@restore@\romannumeral #1\endcsname}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@loadtablebyname}
% Often, we want to access table information by a column width set
% name. We make the maximum column widths accessible, but also the
% information from the previous table that has been using the same
% column width set.
%    \begin{macrocode}
\def\PT@loadtablebyname#1% #1 set name
  {\PT@typeout@{Loading table information for column width set #1.}%
   \expandafter\PT@loadtable\expandafter{\csname PT@widths@#1\endcsname}}%
%   \advance\PT@cols by \PT@restoredcols\relax
%   \expandafter\PT@appendmacro\expandafter\PT@allcols
%     \expandafter{\PT@restoredallcols}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@saveinformation}
% In each table for which the widths get reused (i.e., in all tables
% that use either |\savecolumns| or |\restorecolumns|, we have to store
% all important information for further use.
%    \begin{macrocode}
\def\PT@saveinformation#1% #1 set name
  {\expandafter\def\expandafter\PT@temp\expandafter
     {\csname PT@widths@#1\endcsname}%
   \expandafter\def\expandafter\PT@temp\expandafter
     {\csname PT@restore@\romannumeral\PT@temp\endcsname}%
   \expandafter\gdef\PT@temp{}% start empty
   % this is: \Execute{\Map{\PT@savecolumn{\PT@temp}}\PT@sortedlist}
   \expandafter\Execute\expandafter{\expandafter
     \Map\expandafter{\expandafter\PT@savecolumn
       \expandafter{\PT@temp}}\PT@sortedlist}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@savecolumn}
% A single column is saved by this macro.
%    \begin{macrocode}
\def\PT@savecolumn#1#2% #1 macro name, #2 column name
  {\PT@typeout@{saving column #2 in \string #1 ...}%
   \def\PT@temp{#2}%
   \ifx\PT@temp\PT@nullcol
     \PT@typeout@{skipping nullcol ...}%
   \else
     \PT@typeout@{max=\csname #2.max\endcsname, %
                  width=\csname #2.width\endcsname, %
                  trusted=\csname #2.trusted\endcsname}%
     % we need the column command in here
     % we could do the same in \column, but then the location of
     % \save / \restore matters ...
     \PT@gaddendmacro{#1}{\maxcolumn}%
     \ifnum\csname #2.trusted\endcsname=\PT@true\relax
       \PT@gaddendmacro{#1}{[\PT@true]}%
     \fi
     \edef\PT@temp{\StripColumn{#2}}%
     \PT@addargtomacro{#1}{PT@temp}%
     \PT@addargtomacro{#1}{#2.max}%
     \PT@gaddendmacro{#1}{\column}%
     \PT@addoptargtomacro{#1}{#2.width}%
     \edef\PT@temp{\StripColumn{#2}}%
     \PT@addargtomacro{#1}{PT@temp}%
     \PT@addargtomacro{#1}{#2.type}%
     %\show#1%
   \fi
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@savewidths}
% If we really want to save column width information, then the first
% thing we should worry about is that there might already have been
% a set with the name in question. Therefore, we will call
% |\PT@verifywidths| for that set. In the case that there is no set
% of this name yet, we will schedule the set for verification at the
% end of document.
%    \begin{macrocode}
\newcommand*{\PT@savewidths}[1][default@]
  {\PT@typeout@{Executing \string\savecolumns [#1].}%
   \def\PT@currentwidths{#1}%
   \PT@verifywidths{#1}%
%    \end{macrocode}
% We now reserve a new unique number for this column width set
% by increasing the |\PT@table| counter. We then associate
% the given name (or |default@|) with the counter value and
% restore the widths from the |.aux| file if they are present.
%    \begin{macrocode}
   \global\advance\PT@table by 1\relax
   \expandafter\xdef\csname PT@widths@#1\endcsname
     {\the\PT@table}%
   \PT@loadtable{\PT@table}%
   \ignorespaces}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@restorewidths}
% Restoring information is quite simple. We just load all information
% available.
%    \begin{macrocode}
\newcommand*{\PT@restorewidths}[1][default@]
  {\PT@typeout@{Executing \string\restorecolumns [#1].}%
   \def\PT@currentwidths{#1}%
   \let\PT@inrestore\PT@true
   \PT@loadtablebyname{#1}%
   \ignorespaces}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@comparewidths}
%    \begin{macrocode}
\def\PT@comparewidths#1% #1 full column name
  {\@ifundefined{#1.max}%
     {\PT@typeout@{computed width for #1 is fine ...}}%
     {\ifdim\csname #1.max\endcsname>\csname #1.width\endcsname\relax
        \PT@typeout@{Preferring saved width for \StripColumn{#1}.}%
        \PT@changedtrue
        \PT@colwidth=\@nameuse{#1.max}\relax
        \PT@enamedef{#1.width}{\the\PT@colwidth}%
      \fi}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@trustedmax}
%    \begin{macrocode}
\def\PT@trustedmax#1%
  {\PT@TeXif{\ifnum\csname #1.trusted\endcsname=\PT@true}}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\PT@equalwidths}
%    \begin{macrocode}
\def\PT@equalwidths#1% #1 full column name
  {\@ifundefined{#1.max}{}%
     {\ifdim\csname #1.max\endcsname=\csname #1.width\endcsname\relax
        \PT@typeout@{col #1 is okay ...}%
      \else
        \PT@rerun% a rerun is needed
      \fi}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@verifywidths}
%    \begin{macrocode}
\def\PT@verifywidths#1% #1 column width set name
  {\@ifundefined{PT@widths@#1}%
     {\PT@typeout@{Nothing to verify yet for set #1.}%
      \PT@typeout@{Scheduling set #1 for verification at end of document.}%
      \AtEndDocument{\PT@verifywidths{#1}}}%
     {\PT@typeout@{Verifying column width set #1.}%
      \expandafter\PT@verify@widths\expandafter
        {\csname PT@widths@#1\endcsname}{#1}}}

\def\PT@verify@widths#1#2% #1 set id number, #2 set name
  {\@ifundefined{PT@restore@\romannumeral #1}{}%
     {\begingroup
        \let\column\PT@firstrun@column
        \PT@cols=0\relax%
        \def\PT@allcols{\Nil}%
        \PT@loadtablebyname{#2}%
        \PT@table=#1\relax
        % nullcolumn is not loaded, therefore:
        \expandafter\def\csname\PT@nullcol .width\endcsname{0pt}%
        % checking trust
        \PT@prelazylist
        \All{\PT@trustedmax}{\PT@allcols}%
           {\PT@typeout@{All maximum widths can be trusted -- writing .max!}%
            \PT@save@table{.max}}%
           {\PT@typeout@{Untrustworthy maximums widths -- writing .width!}%
            \PT@rerun
            \PT@save@table{.width}}%
        \PT@postlazylist
      \endgroup}%
   \PT@typeout@{Verification for #2 successful.}}
%    \end{macrocode}
% \end{macro}
%   
% \begin{macro}{\PT@save@table}
% Here we prepare to write maximum column widths to the
% |.aux| file.
%    \begin{macrocode}
\def\PT@save@table#1%
  {\PT@typeout@{Saving column width information.}%
   \if@filesw
     \PT@prelazylist
     {\immediate\write\@auxout{%
        \gdef\expandafter\noexpand
          \csname PT@restore@\romannumeral\PT@table\endcsname
            {\Execute{\Map{\PT@write@column{#1}}\PT@allcols}}}}%
     \PT@postlazylist
   \fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\PT@write@column}
% We define the column command to write to the file.
%    \begin{macrocode}
\def\PT@write@column #1#2%
  {\noexpand\maxcolumn^^J%
    {\StripColumn{#2}}%
    {\@nameuse{#2#1}}}%
%    \end{macrocode}
% \end{macro}
%
% \subsection{The user environments}
%
% It remains to define the three environments to be
% called by the user.
%    \begin{macrocode}
\newenvironment{ptabular}[1][c]%
  {\def\PT@begin{\tabular[#1]}%
   \let\PT@end\endtabular
   \beginpolytable}
  {\endpolytable}

\newenvironment{parray}[1][c]%
  {\def\PT@begin{\array[#1]}%
   \let\PT@end\endarray
   \beginpolytable}
  {\endpolytable}

\def\pboxed{%
   \let\PT@begin\@gobble
   \let\PT@end\empty
   \let\PT@multicolumn\PT@placeinbox
   \expandafter\beginpolytable\ignorespaces}

\let\endpboxed\endpolytable
%    \end{macrocode}
%
% That is all.
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \Finale
\endinput
