Auto generating table

In the following scheme, why do I have to hide & in a macro (\samp) before it works?

\documentclass{article}
\usepackage{catoptions}
\makeatletter
\cptnewcounts{rowcnt,colcnt,maxrow,maxcol}
\def\docols{%
\global\advance\colcnt\@ne
\the\numexpr\rowcnt*\colcnt\relax
\ifnum\colcnt=\maxcol\stopcol\fi
\samp\docols
}
\def\stopcol#1\docols{\fi}
\def\samp{&}
\def\dorows{%
\global\advance\rowcnt\@ne
\global\colcnt\z@
\docols
\ifnum\rowcnt=\maxrow\stoprow\fi
\scr\dorows
}
\def\stoprow#1\dorows{\fi\crcr}
\def\scr{\cr}
\makeatother

\begin{document}
\maxrow4 \maxcol3
\vbox{\halign{&\ \hfil#\hfil\strut\cr\dorows}}
\end{document}

-

1 Answer

The \dorows expansion is performed all in one swoop, generating the table body, and only then TeX will start to expand it looking for & and \cr tokens, if you hide them in macros. Otherwise TeX will see & and stop the column, inserting the u and v part, typesetting it and storing it away. So the dreaded \endtemplate token will find its way in the argument of \stopcol.

If instead you put & and \cr into macros, these won't be expanded until \dorows has finished its work and the table will be safely built.

Notice that \cr is not outer: the problem is exactly the same as with \stopcol, but with \stoprow.

You can see this by changing your input as follows:

\documentclass{article}
\usepackage{catoptions}
\makeatletter
\cptnewcounts{rowcnt,colcnt,maxrow,maxcol}
\newtoks\ahmed
\def\docols{%
\global\advance\colcnt\@ne
\global\ahmed=\expandafter{\the\expandafter\ahmed\the\numexpr\rowcnt*\colcnt\relax}%
\ifnum\colcnt=\maxcol\stopcol\fi
\global\ahmed=\expandafter{\the\ahmed\samp}\docols
}
\def\stopcol#1\docols{\fi}
\def\samp{&}
\def\dorows{%
\global\advance\rowcnt\@ne
\global\colcnt\z@
\docols
\ifnum\rowcnt=\maxrow\stoprow\fi
\global\ahmed=\expandafter{\the\ahmed\scr}\dorows
}
\def\stoprow#1\dorows{\fi\global\ahmed=\expandafter{\the\ahmed\crcr}}
\def\scr{\cr}
\makeatother

\begin{document}
\maxrow4 \maxcol3
\vbox{\halign{&\ \hfil#\hfil\strut\cr\dorows\showthe\ahmed\the\ahmed}}
\end{document}


The \show command will output

> 1&2&3\cr 2&4&6\cr 3&6&9\cr 4&8&12\crcr .
l.27 ... \hfil#\hfil\strut\cr\dorows\showthe\ahmed
\the\ahmed}}$$ With this approach you can use & and \cr, because they would be protected by the braces of the token register assignment. - But the above result of \show\ahmed indicates that $$\vbox{&...\dorows\the\ahmed}}$$ can't be a solution. It will inherit only the last (max.) values of the counters. I think you need to remove \the\ahmed after \showthe\ahmed, to indicate that you mean $$\vbox{&...\dorows\showthe\ahmed}} only as an illustration. –  Ahmed Musa Jun 2 '12 at 21:02
@AhmedMusa You are right, I forgot an \expandafter. Fixed. –  egreg Jun 2 '12 at 21:07
Then you need to also replace the outcome of \showthe\ahmed. –  Ahmed Musa Jun 2 '12 at 21:14
@AhmedMusa I don't understand: the \showthe\ahmed shows the contents of the register, while \the\ahmed delivers it to the \halign for printing. –  egreg Jun 2 '12 at 21:18
I have added something to the original question. –  Ahmed Musa Jun 2 '12 at 23:57