% !TeX spellcheck = fr_FR
% !TeX encoding = ISO-8859-1
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                                                                          %%
%%                           Code source du livre                           %%
%%                     � Apprendre � programmer en TeX �                    %%
%%                                                                          %%
%%                                   ___                                    %%
%%                                                                          %%
%%                     � 2014-2020 Christian Tellechea                      %%
%%                                                                          %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ___________________________________________________________________________
%|                                                                           |
%|                    Encodage ISO 8859-1 (latin1)                           |
%|               � compiler avec pdflatex en mode pdf                        |
%|___________________________________________________________________________|
\RequirePackage{etex}
\documentclass[fontsize=10pt,chapterprefix=true]{scrbook}

\newwrite\wtest
\newread\rtest

\usepackage[latin1]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[
       paperwidth=16.8275cm,paperheight=26.035cm,
       headsep=.5cm,headheight=1cm,
       footskip=1cm,
       twoside,
       lmargin=2.2cm,
       rmargin=2.8775cm,
       tmargin=2.5cm,
       bmargin=3cm
       ]{geometry}% largeur texte = 16.8275-(2.8775+2.2)=11,75 cm

\usepackage[table]{xcolor}
\definecolor{shadecolor}{rgb}{0.86078,0.86078,0.86078}% couleur de fond des environnements "regle"

\usepackage{
       metalogo,
       tikz,
       xspace,
       dashbox,
       fancybox,
       enumitem,
       longtable,
       framed,
       graphicx,
       amsmath,
       needspace
}
\xspaceaddexceptions{\footnote\verb)}
\usetikzlibrary{decorations}
\usepgflibrary{decorations.pathmorphing}
% ____________________________________________________________________________
%|                                                                            |
%|                     Macros d�finies dans le livre                          |
%|                                                                            |
\input progtexmacro.tex%                                                      |
%|                                                                            |
%|____________________________________________________________________________|

\makeatletter

% ____________________________________________________________________________
%|                                                                            |
%|                         environnements "liste"                             |
%|                                                                            |
\newlist{algo}{enumerate}{4}
\setlist[algo]{leftmargin=*,labelindent=\main@parindent,itemsep=0pt,topsep=4pt,parsep=1.5pt,before=\small}
\setlist[algo,1]{label=\arabic*),topsep=2pt,ref=\arabic*}
\setlist[algo,2]{label=\alph*),topsep=1pt,ref=\thealgoi.\alph*}
\setlist[algo,3]{label=\roman*),topsep=1pt,ref=\thealgoii.\roman*}
\setlist[algo,4]{label=--,topsep=1pt,ref=\thealgoiii.\roman*}

\setlist[enumerate]{leftmargin=*,labelindent=\main@parindent,itemsep=0.3pt,topsep=1pt,parsep=1pt,partopsep=0pt}

\setlist[itemize]{leftmargin=*,labelindent=\main@parindent,itemsep=0.3pt,topsep=1pt,parsep=1pt,partopsep=0pt,label=--}
%|                                                                            |
%|                        fin environnements "liste"                          |
%|____________________________________________________________________________|

\usepackage[bottom]{footmisc}

\usepackage{scrlayer-scrpage}
\pagestyle{scrheadings}
\clearscrheadfoot
\cehead{\leftmark}
\cohead{\rightmark}
\lehead{\llap{\normalfont\bfseries\thepage\kern4mm }}
\rohead{\rlap{\normalfont\bfseries\kern4mm \thepage}}
\automark[chapter]{part}
\renewcommand\partmarkformat{\ifnum\arabic{part}>0 \normalfont\biolinum\small\itshape\thepart. \fi}
\renewcommand\chaptermarkformat{\normalfont\biolinum\small\itshape\thechapter. }

% ____________________________________________________________________________
%|                                                                            |
%|                              Polices                                       |
%|                                                                            |
\usepackage{amssymb,textcomp,eurosym,libertine}
\usepackage[libertine]{newtxmath}
\newcommand*\GMC@scale{0.8}
\usepackage[scaled=0.8]{GoMono}
\DeclareRobustCommand*\libLegacyGlyph[1]{{\ifcsname fxl@#1\endcsname\@nameuse{fxl@#1}\else\errmessage{glyphe fxl@#1 non d�fini}\fi}}
\DeclareRobustCommand*\bioLegacyKeyGlyph[1]{{\ifcsname fxk@#1\endcsname\@nameuse{fxk@#1}\else\errmessage{glyphe fxk@#1 non d�fini}\fi}}
\newcommand*\DeclareTextGlyphX[5]{\@namedef{#1@#4}{{\fontfamily{#3}\fontencoding{#2}\selectfont\char#5\relax}}}
\DeclareTextGlyphX{fxk}{U}{fxke1}{T_a_b}{117}
\DeclareTextGlyphX{fxk}{U}{fxke1}{E_n_t_e_r}{118}
\DeclareTextGlyphX{fxk}{U}{fxke1}{A_l_t_G_r}{114}
\DeclareTextGlyphX{fxk}{U}{fxk00}{A}{65}
\DeclareTextGlyphX{fxk}{U}{fxk00}{R}{82}
\DeclareTextGlyphX{fxk}{U}{fxk00}{seven}{55}
\DeclareTextGlyphX{fxl}{U}{fxle0}{Q_u}{72}
\DeclareTextGlyphX{fxl}{U}{fxle0}{uniE007}{7}
\newcommand*\Qu{\libLegacyGlyph{Q_u}}% <- pour �viter de cr�er une fonte virtuelle
%|                                                                            |
%|                            fin Polices                                     |
%|____________________________________________________________________________|

\usepackage{lettrine}
\usepackage[
       protrusion=true,
       expansion=true,
       stretch=10,
       shrink=5,
       tracking=true,
       final,
       babel=true]{microtype}
\usepackage[autolanguage]{numprint}
% ____________________________________________________________________________
%|                                                                            |
%|                               Mises en forme                               |
%|                                                                            |
\let\lcodedelim=\langle
\let\rcodedelim=\rangle
\DeclareRobustCommand\codeelement[1]{% met en forme <"#1">
       \ensuremath\lcodedelim\textit{#1}\ensuremath\rcodedelim
}
\let\Verb=\verb
\def\def@visible@space{%
       \setbox0\hbox{x}%
       \def\visible@space{%
               \leavevmode
               \kern.1ex
               \vrule width0.4pt height0.5ex depth0.2ex\relax
               \vrule width\dimexpr\wd0-.8pt-.2ex\relax height\dimexpr.4pt-.2ex\relax depth0.2ex\relax
               \vrule width0.4pt height0.5ex depth0.2ex\relax
               \kern.1ex
               }%
}
\def\verb{%
       \relax\ifmmode\hbox\else\leavevmode\null\fi
       \bgroup
               \ttfamily
               \hyphenchar\font=-1
               \for\ii=0 to 255 \do {\catcode\ii=12 }%
               \catcode`\~13
               \obeylines \verbatim@font \@noligs \hyphenchar\font=-1
               \ifstarred{\def@visible@space\letactive\ =\visible@space\catcode`\~12 \verb@i}{\letactive\ =\space\catcode`\~12\frenchspacing\verb@i}%
}
\def\verb@i#1{%
               \def\verb@ii##1#1{\verb@iii{##1}}%
               \verb@ii
}
\catcode`\>=13
\catcode`\<=13
\def\verb@element#1>{\codeelement{#1}}
\def\verb@iii#1{%
               \ifin{#1}<%
                       {\def\temp@l{#1}\let\temp@r\temp@l%
                       \leftofsc\temp@l<%
                       \rightofsc\temp@r<%
                       \exparg\ifin\temp@r>%
                               {\addtomacro\temp@l\verb@element
                               \eaddtomacro\temp@l\temp@r
                               \exparg\verb@iii\temp@l
                               }
                               {#1\egroup}%
                       }
                       {#1\egroup}%
}
\catcode`\>=12
\catcode`\<=12

\newcount\exercice@cnt
\exercice@cnt\z@

\newmacro\defactive[\def]1{%
       \catcode`#2=13
       \begingroup
       \lccode`~=`#2
       \lowercase{\endgroup#1~}}

\newcounter{exemple}[part]

\newenvironment{centrage}[1][3.5pt]
       {\ifvmode\removelastskip\fi
       \list{}{\leftmargin\z@\parsep\z@\topsep#1\relax}%
       \centering\item\relax
       }%
       \endlist

\newcommand\boxtoken[2][\string]{%
       \begingroup
               \fboxsep\boxtokensep
               \fbox{\ttfamily\vphantom{Ailpj}#1#2}%
       \endgroup
       \xspace
}
\newcommand*\boxtokensep{0.3pt}

\newcommand*\TeXhead{$\ggg$}
\newcommand*\Hex[1]{\hbox{$\mathsf{#1}_{\scriptscriptstyle\mathsf h}$}}
\newcommand*\bin[1]{\textit{#1}}
\newcommand*\latin{\texttt{latin1}\xspace}
\newcommand*\utf{\texttt{UTF8}\xspace}

\newenvironment{exercice}
       {%
       \needspace{3.5\baselineskip}%
       \setlist[enumerate]{leftmargin=*,labelindent=\main@parindent,itemsep=0pt,topsep=1pt,parsep=1pt}%
       \parindent\z@
       \parskip2pt plus.5pt minus.5pt
       \global\advance\exercice@cnt\@ne
       \bigbreak
       \small\noindent
       \rule{1.25ex}{1.25ex}\kern1ex \textsc{\textbf{Exercice \number\exercice@cnt}}\par\nobreak
       }
       {\ifvmode
               \vskip\dimexpr2pt-\baselineskip-\lastskip\relax
       \fi
       \hfill\rule{1.25ex}{1.25ex}\bigbreak}

\FrameSep=5pt
\newcount\cnt@regle
\newwrite\reglewrite
\immediate\openout\reglewrite=regles.txt
\immediate\write\reglewrite{%
       \string\newcount\string\recapreglecnt\string^^J%
       \string\recapreglecnt=0\relax
       \string^^J%
}
\newenvironment{regle}[1][R�gle]{%
       \global\advance\cnt@regle\@ne
       \begingroup
               \gdef\titre@regle{#1}%
               \for\xxx=0 to 255\do{\catcode\xxx=12 }%
               \captureregle
       }
       {}
\begingroup\edef\temp{\endgroup\def\noexpand\captureregle##1\string\end\detokenize{{regle}}}
\temp{%
       \endgroup
       \newlinechar`\^^M
       \immediate\write\reglewrite{%
               \string\begin{recapregle}#1\string\end{recapregle}\string^^J%
               }%
       \begingroup
               \parskip2pt plus.25pt minus.25pt
               \setlist[itemize]{leftmargin=2em,itemsep=0pt,topsep=1pt,parsep=1pt,label=--}%
               \newlinechar`\^^M
               \everyeof{\noexpand}%
               \makeatletter
               \scantokens{%
                       \parindent\z@
                       \shaded
                               {\bfseries\scshape\number\cnt@regle{} - \titre@regle}%
                               \par\nobreak
                               #1%
                       \endshaded
                       }%
       \endgroup
       \end{regle}%
}%

\newenvironment{recapregle}%
       {\bigbreak
       \global\advance\recapreglecnt 1
       \let\label=\gobone
       \small
       \parindent=0pt
       \parskip1pt plus.25pt minus.25pt
       \setlist[itemize]{leftmargin=3.5em,itemsep=0pt,topsep=1pt,parsep=1pt,label=--}%
       \textbf{\number\recapreglecnt\relax.\kern0.33333em}%
       }
       {}

\newcommand\solution[1][]{%
       \needspace{3\baselineskip}%
       \smallbreak\noindent%\incorrectiontrue
       {\fboxsep\z@\fboxrule.5pt \fbox{\vrule height1ex width\z@\kern1ex }}%
       \hspace{1ex}\textsc{\textbf{Solution\ifempty{#1}{}{ #1}}}\par\nobreak
}

% Centre la ligne de code en mode verbatim
% Utilisation : \centrecode*-code-
% "*" facultative. Si pr�sent, les espaces sont rendus visibles
% code est un code se trouvant entre 2 caract�res identiques.
% Si * : ne tient pas compte des "<" et ">"
\def\centrecode{\def\space@def{\defactive\ {\space}}\centrecode@}

\def\centrecodespc{\def\space@def{\catcode`\ =12 }\centrecode@}

\def\centrecode@{%
       \par\unskip
       \begingroup
               \parskip\z@
               \catcode`\�=13
               \begingroup
                       \lccode`\~`\�\relax
                       \lowercase{\endgroup\long\def~##1~}{%
                               \begingroup
                                       \catcode`\{=1 \catcode`\}=2 \catcode`\#=6 \catcode`\\=0 \catcode`\$=3
                                       \catcode`\f=11
                                       \endlinechar=-1
                                       \scantokens{##1}%
                               \endgroup
                               }% �chappement de �...�
               \parindent\z@\let\do\@makeother\dospecials
               \defactive\,{\kern\z@\string,}%
               \defactive\-{\kern\z@\string-}%
               \defactive\^^M{\normalfont\ttfamily\color{black}\cr{}}%
               \defactive\^^I{{ }{ }{ }{ }}% tab = 4 espaces
               \defactive\%{\itshape\color{gray}\char`\% }%
               \space@def
               \@ifstar
                       {\let\centrecode@iii=\centrecode@star
                       \defactive\<{\string<{}}%
                       \defactive\>{\string>{}}%
                       \centrecode@i
                       }
                       {\let\centrecode@iii=\centrecode@nostar
                       \centrecode@i
                       }%
}

\def\centrecode@i#1{%
       \def\centrecode@ii##1#1{\centrecode@iii{##1}}%
       \centrecode@ii}

\def\centrecode@nostar#1{% #1 est le code
       \ifin{#1}<%
               {\def\temp@l{#1}\let\temp@r\temp@l%
               \leftofsc\temp@l<%
               \rightofsc\temp@r<%
               \exparg\ifin\temp@r>%
                       {\addtomacro\temp@l\centrecode@element
                       \eaddtomacro\temp@l\temp@r
                       \exparg\centrecode@nostar\temp@l
                       }%
                       {\centrecode@star{#1}}%
               }%
               {\centrecode@star{#1}}%
}

\def\centrecode@star#1{%
       \centrage{}\leavevmode\vbox{\small\ttfamily\halign{##\hfill\cr#1\cr\crcr}}\endcentrage
       \endgroup\ignorespaces
}
\def\centrecode@element#1>{\codeelement{#1}}

% Utilisation : \indentcode*[dim]-code-
% "*" facultative. Si pr�sente, les lignes sont num�rot�es
% [dim] est l'indentation du code par rapport au d�but des lignes. 3em par d�faut
% code se trouve entre 2 caract�res identiques et peut comporter des retours � la ligne
\newif\ifindencodenum
\indencodenumfalse
\newcount\indentcode@cnt
\newcommand*\indentcode{%
       \begingroup
       \indentcode@cnt=\z@
       \let\do\@makeother\dospecials
       \catcode`\?12 \catcode`\!12
       \@ifstar
               \indentcode@i
               {\defactive\ { }%
                \indentcode@i
                }%
}

\newcommand*\indentcodeactivechars[1]{%
       \defactive\^^M{\par\hspace{#1}}%
       \defactive\^^I{{ }{ }{ }{ }}% tab = 4 espaces
       \catcode`\�=13
       \begingroup
               \lccode`\~`\�\relax
               \lowercase{\endgroup\long\def~##1~}{%
                       \begingroup
                               \catcode`\{=1 \catcode`\}=2 \catcode`\#=6 \catcode`\\=0 \catcode`\$=3
                               \catcode`\f=11
                               \endlinechar=-1
                               \scantokens{##1}%
                       \endgroup
                       }% �chappement �...�
}

\newcommand*\indentcode@i[1][\main@parindent]{%
       \parindent\z@
       \parskip\z@
       \ttfamily\small
       \ifindencodenum
               \everypar{\advance\indentcode@cnt\@ne\llap{\footnotesize$\scriptstyle\number\indentcode@cnt$\space}}%
       \fi
       \par\smallskip\nobreak\noindent\hspace{#1}%
       \indentcodeactivechars{#1}%
       \indentcode@ii
}

\def\indentcode@ii#1{%
       \expandafter\defactive\csname#1\endcsname{\smallbreak\endgroup\ignorespaces}%
}

\newcommand*\boxcs[2]{%
       {\boxput*(0,1){\fboxsep\z@\colorbox{white}{\leavevmode\kern1pt\footnotesize\string#1\kern1pt}}{\fboxsep=7pt\fbox{#2}}}%
}

\newcount\node@cnt
\newcommand*\jumptok[2][\expandatfer]{%
       \begin{tikzpicture}[baseline,inner sep=1pt,outer sep=0pt]
               \def\exp@tok{\ttfamily\string#1}%
               \def\end@tok{#2}%
               \small
               \makeatletter
               \@makeother\{\@makeother\}\@makeother\#%
               \node@cnt\z@
               \def\previous@node{n@0}%
               \node[anchor=base,fill=black!25](n@0){\strut\exp@tok};
               \jump@tok
}

\def\jump@tok#1#2#3{%
       \advance\node@cnt\@ne
       \node[anchor=base west,at=(\[email protected] east)](jumped@tok){\ttfamily\strut\string#1};
       \if\end@tok\noexpand#3%
               \node[draw,anchor=base west,at=([email protected] east)](n@\number\node@cnt){\ttfamily\strut\string#2};
               \draw[-stealth,shorten >=2pt](\previous@node) to[out=30,in=150] (n@\number\node@cnt);
               \end{tikzpicture}%
               \expandafter\@gobbletwo
       \else
               \node[fill=black!25,anchor=base west,at=([email protected] east)](n@\number\node@cnt){\strut\exp@tok};
               \draw[-stealth,shorten >=2pt](\previous@node) to[out=30,in=150] (n@\number\node@cnt);
               \edef\previous@node{n@\number\node@cnt}%
               \expandafter\jump@tok
       \fi{#2}{#3}%
}

\def\showcodes#1{%
       \hbox{%
               \texttt{\string#1}%
               (\number`#1\relax\thinspace\string;\thinspace\number\catcode`#1\relax)%
       }%
       \xspace
}

\newbox\testbox
\newif\ifshow@dimen
\newcommand*\dimenbox{\@ifstar{\show@dimenfalse\dimenbox@i}{\show@dimentrue\dimenbox@i}}
\newcommand*\dimenbox@i[2][100pt]{%
       \setbox\testbox\hbox{\fontsize{#1}{#1}\selectfont #2}%
       \begin{tikzpicture}[inner sep=0pt,outer sep=0pt,minimum size=0pt,baseline,line width=0.2pt]
               \node[anchor=base west,draw,inner sep=-0.1pt]at(0,0)(boite){\fontsize{#1}{#1}\selectfont#2};
               \ifshow@dimen
                       \draw[gray,overlay]([xshift=-.8cm]boite.base west)--([xshift=.5cm]boite.base east)node[pos=0,anchor=south west,black,outer sep=1pt]{\tiny ligne de}node[pos=0,anchor=north west,black,outer sep=1pt]{\tiny base};
                       \ifdim\dp\testbox>5pt
                               \draw[stealth-stealth,overlay]([xshift=.4cm]boite.base east)--([xshift=.4cm]boite.south east)node[pos=0.5,anchor=west,outer sep=3pt]{\ttfamily\scriptsize\string\dp=\the\dp\testbox};
                       \else
                               \path([xshift=.4cm]boite.base east)--([xshift=.4cm]boite.south east)node[pos=0.5,anchor=west,outer sep=3pt]{\ttfamily\scriptsize\string\dp=\the\dp\testbox};
                       \fi
                       \draw[stealth-stealth,overlay]([xshift=.4cm]boite.base east)--([xshift=.4cm]boite.north east)node[pos=0.5,anchor=west,outer sep=3pt]{\ttfamily\scriptsize\string\ht=\the\ht\testbox};
                       \draw[stealth-stealth]([yshift=.2cm]boite.north west)--([yshift=.2cm]boite.north east)node[pos=0.5,anchor=south,outer sep=3pt]{\ttfamily\scriptsize\string\wd=\the\wd\testbox};
               \fi
               \draw[fill,black,overlay](boite.base west)circle(1pt);%
       \end{tikzpicture}%
}
%|                                                                            |
%|                             fin mises en forme                             |
%|____________________________________________________________________________|

% ____________________________________________________________________________
%|                                                                            |
%|                             Commande \showcode                             |
%|                                                                            |
\newbox\strut@box
\newif\if@codeline
\newif\if@errcode
\newif\if@comment
\newcount\code@line
\newcount\code@count
\newwrite\codewrite
\immediate\openout\codewrite=progtexcode.txt
\exactwrite\codewrite|%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                                                                          %%
%%                        Codes donn�s dans le livre                        %%
%%                    � Apprendre � programmer en TeX �                     %%
%%                                                                          %%
%%                           Encodage ISO 8859-1                            %%
%%                                   _____                                  %%
%%                                                                          %%
%%                     � 2014-2020 Christian Tellechea                      %%
%%                                                                          %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Les codes et les macros comment�s donn�s dans ce fichier sont diffus�s sous
% la licence LaTeX project public license (LPPL) 1.2
%
% https://www.latex-project.org/lppl/lppl-1-2/
% https://www.latex-project.org/lppl/lppl-1-2.txt
%
% Attention : ce fichier n'a pas vocation � �tre compil�
\endinput|
\let\shownumline\@codelinetrue
\let\hidenumline\@codelinefalse
\shownumline
\newcommand\encadre[2]{%0 = encadre 1=d�but 2=milieu 3=fin
       \leavevmode
       \frboxrule=0.4pt \frboxsep=3pt
       \setbox\z@\hbox{\kern\frboxsep#2\kern\frboxsep}%
       \hbox{%
               \vrule width\frboxrule
               \vtop{%
                       \vbox{%
                               \ifnum#1<2
                                       \hbox to\wd\z@{%
                                               \bfseries\footnotesize
                                               \hrulefill
                                               \kern.5em
                                               \setbox\z@\hbox{Code \ifnum\arabic{part}>\z@\no\thepart-\fi\number\code@count}%
                                               \ht\z@\z@ \dp\z@\z@
                                               \lower.5ex\box\z@
                                               \kern.5em
                                               \hrulefill
                                               }%
                               \fi% r�glure sup�rieure
                               \kern\frboxsep% espace haut
                               \box\z@
                               }%
                       \kern\dimexpr\frboxsep+.5ex\relax% espace bas
                       \ifnum#1=0 \hrule height\frboxrule\fi% r�glure inf�rieure
                       \ifnum#1=3 \hrule height\frboxrule\fi
               }% r�glure inf�rieure
               \vrule width\frboxrule
       }%
}

\newcommand*\showcode{\@errcodefalse\showcode@i}

\newcommand*\errcode{\@errcodetrue\showcode@i}

\def\showcodeactivechars{}

\newcommand*\showcode@i[1][]{%
       \needspace{3.5\baselineskip}%
       \global\advance\code@count1
       \edef\saved@state{%
               \tolerance=\the\tolerance\relax
               \emergencystretch=\the\emergencystretch\relax
               \hfuzz=\the\hfuzz
               \vfuzz=\the\vfuzz
               }%
       \medbreak
       \begingroup
               \parindent\z@
               \parskip\z@
               \code@line\z@
               \def\aux@code{#1}%
               \begingroup
                       \for\xx=0 to 255 \do{\catcode\xx=12 }%
                       \showcode@ii
}

\def\assign@execcode#1\@nil{\xdef\execcode@code{#1}}

\newcommand*\showcode@ii[1]{%
                       \def\showcode@iii##1#1{% ##1 est le code o� tous les catcodes sont de 12
                                       \catcode`\�=13
                                       \begingroup
                                               \lccode`\~=`\�
                                       \lowercase{\endgroup\def~####1~}{}%
                                       \newlinechar`\^^M
                                       \everyeof{\@nil}%
                                       \expandafter\assign@execcode\scantokens{##1}%
                                       \immediate\write\codewrite{^^J^^J%
                                               ****************** Code \number\code@count \space******************^^J%
                                               \execcode@code
                                               ****************** Fin code ******************}%
               \endgroup
               \def\showcode@code{##1}%
               \afterassignment\showcode@iv
               \if@errcode\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
                       {\def\err@message}
                       {\let\err@message\@empty}%
               }%
               \showcode@iii
}
\definecolor{codegray}{gray}{0.375}% gris pour les commentaires dans \showcode
\newcommand*\showcode@iv{%
               \def\FrameCommand{\encadre0}%
               \def\FirstFrameCommand{\encadre1}%
               \def\MidFrameCommand{\encadre2}%
               \def\LastFrameCommand{\encadre3}%
               \topsep1.5ex %espace avant l'encadrement
               \par\nointerlineskip\nobreak
               \edef\restorevbadness{\vbadness=\the\vbadness\relax}%
               \vbadness=10000
               \MakeFramed{\advance\hsize-\width\FrameRestore}%
                       \begingroup
                               \footnotesize
                               \everyeof{\noexpand}%
                               \begingroup
                                       \if@codeline\everypar{\num@code}\fi
                                       \gray@line
                                       \let\do\@makeother\dospecials
                                       \catcode`\�=13
                                       \begingroup
                                               \lccode`\~`\�\relax
                                               \lowercase{\endgroup\long\def~##1~}{%
                                                       \begingroup
                                                               \catcode`\{=1 \catcode`\}=2 \catcode`\#=6 \catcode`\\=0 \catcode`\$=3
                                                               \catcode`\f=11 \catcode`\ =10
                                                               \def\idxmp{%
                                                                       \relax
                                                                       \edef\saved@at@catcode{\the\catcode`\@}%
                                                                       \catcode`\@11
                                                                       \@ifstar
                                                                               {\let\print@idx\@gobble\index@macro@perso}
                                                                               {\let\print@idx\@gobble\index@macro@perso}%
                                                               }%
                                                               \def\idx{%
                                                                       \relax\makeatletter
                                                                       \@ifstar
                                                                               {\let\print@idx\@gobble\idx@}%
                                                                               {\let\print@idx\@gobble\idx@}%
                                                               }%
                                                               \scantokens{##1}%
                                                       \endgroup
                                                       }% �chappement �...�
                                       \defactive\%{\unexpanded{\@commenttrue\itshape\color{codegray}\%}}% commentaire
                                       \defactive\^^M{\unexpanded{\if@comment\normalfont\ttfamily\color{black}\fi\@commentfalse}\par\leavevmode}% retour charriot
                                       \normalfont\renewcommand*\ttdefault{GMC-TLF}\ttfamily
                                       \setbox\z@\hbox{0}\edef\tt@spc{\hskip\the\wd\z@\relax}%
                                       \catcode`\ =13
                                       \begingroup
                                               \lccode`\~`\ \relax
                                               \lowercase{\endgroup\let~\tt@spc}%
                                       \defactive\^^I{\tt@spc\tt@spc}% tabulation
                                       \defactive\,{\string,{}}% ligatures
                                       \defactive\<{\string<{}}%
                                       \defactive\>{\string>{}}%
                                       \defactive\-{\string-{}}%
                                       \defactive\`{\string`{}}%
                                       \defactive f{\string f{}}%
                                       \showcodeactivechars% �ventuelles modif de caract�res actifs
                                       \endlinechar-1
                                       \scantokens\expandafter{\showcode@code}%
                               \endgroup
                               \removelastskip\par\nointerlineskip\nobreak
                               \ligneH{\kern4pt }%
                               \par%\nobreak
                               \if@errcode\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
                                       {\ttfamily\err@message}
                                       {\catcode`\�=13
                                       \begingroup
                                               \lccode`\~`\�\relax
                                               \lowercase{\endgroup\def~##1~}{}%
                                       \xdef\showcodehisze{\the\hsize}%
                                       \newlinechar`\^^M
                                       \saved@state
                                       \microtypesetup{expansion=false,protrusion=false,tracking=false}%
                                       \aux@code
                                       \edef\nstiflevel@a{\number\currentiflevel}%
                                       \scantokens\expandafter{\execcode@code}\relax
                                       \edef\nstiflevel@b{\number\currentiflevel}%
                                       \ifnum\nstiflevel@a=\nstiflevel@b\relax\else\errmessage{Erreur de if : \number\code@count}\fi
                                       }%
                               \par\nointerlineskip\nobreak
                       \endgroup
               \endMakeFramed
               \restorevbadness
       \endgroup
       \medbreak
}

\newcommand*\ligneH[2][4pt]{%
       \vbox{\offinterlineskip\hsize\linewidth
               \null
               #2%
               \hrule width\linewidth\kern#1\relax\null% 4pt = espace entre ligne et ce qu'il y a dessous
       }%
}

\newcommand*\gray@line{%
       \everypar\expandafter{%
               \the\everypar
               \edef\color@line{\noexpand\colorbox{gray!\ifodd\code@line 35\else 20\fi}}% ou "50\else 35" pour l'impression
               \setbox\strut@box\hbox{\vphantom{�pj}}%
               \dp\strut@box\dimexpr\dp\strut@box+1.25pt\relax
               \ht\strut@box\dimexpr\ht\strut@box+1.25pt\relax
               \setbox\strut@box\hbox{%
                       \fboxsep\z@
                       \color@line{\box\strut@box\kern\dimexpr\linewidth-7.5pt\relax}%
               }%
               \wd\strut@box\z@
               \dp\strut@box\dimexpr\dp\[email protected]\relax
               \ht\strut@box\dimexpr\ht\[email protected]\relax
               \box\strut@box
       }%
}

\newcommand*\num@code{%
       \hb@[email protected]{%
               \hss
               \global\advance\code@line\@ne
               \tiny\number\code@line
               \kern2.5pt}%
}

\newcommand*\defline[1]{\xdef#1{\number\code@line}}
%|                                                                            |
%|                               fin \showcode                                |
%|____________________________________________________________________________|

% ____________________________________________________________________________
%|                                                                            |
%|                   Mise en forme tdm, sectionnement                         |
%|                                                                            |
\usepackage{titletoc}

\newcommand*\partminitoc{%
       \edef\parksip@saved{\the\parskip}\parskip0pt
       \vspace{1.5cm}%
       \normalsize\normalfont
       \startcontents[part]
       \begingroup
               \noindent\bfseries\large
               Sommaire\hfill\null\par\vskip3pt
       \endgroup
       \hrule height1pt depth0pt
       \smallskip
       \renewcommand*\l@chapter[2]{%
               \ifnum\c@tocdepth>\m@ne
                       \addpenalty{-\@highpenalty}%
                       \vskip 2pt \@plus\p@
                       \@tempdima1.5em
                       \begingroup
                       \parindent \z@ \rightskip \@pnumwidth
                       \parfillskip-\@pnumwidth
                       \leavevmode \normalfont
                       \advance\leftskip\@tempdima
                       \hskip-\leftskip
                       {##1}\nobreak\dotfill\nobreak\hb@xt@\@pnumwidth{\hss ##2}\par
                       \penalty\@highpenalty
                       \endgroup
               \fi
       }
       \printcontents[part]{part-}{0}{\setcounter{tocdepth}{0}}%
       \vskip5pt
       \hrule height1pt depth0pt%\titlerule[1pt]
       \parskip\parksip@saved\relax
}

\def\defpartcomment{\def\part@comment}
\defpartcomment{}

\renewcommand*\partformat{%
       \normalfont\large\sffamily\bfseries\scshape
       \hfill\MakeUppercase{\partname}\hfill\null
       \vskip.5cm
       \setbox\z@\hbox{\normalfont\Huge\sffamily\bfseries
                       \libLegacyGlyph{uniE007}%
                       }%
               \hfill
               \ifnum\c@part>0
                       {\normalfont\Huge\sffamily\bfseries
                       \libLegacyGlyph{uniE007}%
                       }%
               \else
                       \vphantom{\box\z@}%
               \fi
               \hfill\null\endgraf
               \fontsize{20}{20}\selectfont\centering
}

\renewcommand*\partheadendvskip{%
       \partminitoc
       \vfill
       \unless\ifx\part@comment\@empty
               \noindent\hfill
               \begin{minipage}{0.65\linewidth}
                       \biolinum
                       \rightskip0pt \leftskip0pt \parindent\z@
                       \hsize5cm
                       \small\null\part@comment\par
               \end{minipage}%
               \global\let\part@comment\@empty
               \vskip2cm
       \fi
}
\addtokomafont{chapterprefix}{\raggedleft}
\addtokomafont{chapter}{\huge\bfseries\scshape\raggedleft}
\renewcommand*\chapterformat{%
       \hfill
       \hbox{\normalfont\bfseries\Large\color{gray}\chapappifchapterprefix{\nobreakspace}\fontsize{72}{80}\selectfont\lower .5ex\hbox{\thechapter}}
       \vskip1cm
}%
\renewcommand*\chapterheadendvskip{\vskip2cm }
\renewcommand*\chapterheadstartvskip{\vskip0.2\vsize}
%|                                                                            |
%|                 fin mise en forme tdm, sectionnement                       |
%|____________________________________________________________________________|

\usepackage[french]{babel}
\frenchbsetup{StandardLists=true,og=�,fg=�}
\selectlanguage{french}

% ____________________________________________________________________________
%|                                                                            |
%|                   Mise en forme notes bas de page                          |
%|                                                                            |
\parindentFFN\parindent
%|                                                                            |
%|                 fin mise en forme notes bas de page                        |
%|____________________________________________________________________________|

% ____________________________________________________________________________
%|                                                                            |
%|                                  Index                                     |
%|                                                                            |
\usepackage{imakeidx}% index multiples
\makeindex[
       title=Index g�n�ral,
       columns=2,
       intoc=true,
       program=texindy,
       options=-M xindstyle.xdy -L french
]
\indexsetup{toclevel=part}
\makeindex[
       name=macros,
       title=Index des macros d�finies dans ce livre,
       columns=2,
       intoc=true,
       program=texindy,
       options=-M xindstyle.xdy -L french
]

\immediate\openout\wtest=xindstyle.xdy

\exactwrite\wtest|(require "page-ranges.xdy")
(define-location-class "arabic-page-numbers"
                      ("arabic-numbers") :min-range-length 1)
(markup-locclass-list :open "\quad " :sep ", ")
(define-attributes (("etc")))
(markup-locref :open "\hyperpage{" :close "}, \ldots" :attr "etc")
(define-crossref-class "voir" :unverified)
(markup-crossref-list :class "voir" :open "\textit{voir} " :sep ", ")
(define-crossref-class "voiraussi" :unverified)
(markup-crossref-list :class "voiraussi" :open "\textit{voir aussi} " :sep ", ")
(define-location-class-order (
  "roman-page-numbers"
  "arabic-page-numbers"
  "alpha-page-numbers"
  "Roman-page-numbers"
  "Alpha-page-numbers"
  "see"
  "voir"
  "voiraussi"))
(markup-locref :open "\hyperpage{" :close "}")
(markup-locref :open "\hyperpage{" :close "}" :attr "hyperpage")|

\immediate\closeout\wtest
\usepackage{xstring}

\let\list@macro@perso\empty% liste des macros perso d�j� rencontr�es

\catcode`\W=3
\def\noindexlist{W}% liste des entr�es � ignorer lors de la mise en index

\long\def\forbidindex#1{% n'indexe plus l'entr�e "#1" jusqu'� ordre contraire
       \expandafter\global\expandafter\long\expandafter\def\expandafter\noindexlist\expandafter{\noindexlist#1W}% ajoute l'entr�e � la liste
}

\long\def\allowindex#1{% autorise l'index de l'entr�e "#1"
       \long\def\allowindex@i##1W#1W##2\allowindex@i{\global\long\def\noindexlist{##1W##2}}%
       \expandafter\ifin\expandafter{\noindexlist}{W#1W}%
               {\allowindex@i#1\allowindex@i}%
               {}%
}
\catcode`\W=11

\newcommand\idxmp{%
       \relax
       \edef\saved@at@catcode{\the\catcode`\@}%
       \catcode`\@11
       \@ifstar{\let\print@idx\@gobble\index@macro@perso}{\let\print@idx\@firstofone\index@macro@perso}%
}

\let\oldparagraph=�
\letactive �\idxmp

\def\index@macro@perso#1{%
       \edef\temp@{\noexpand\substtocs\noexpand\temp@{\string#1}{\string @}}\temp@{\char64 }%
       \edef\temp@{\expandafter\gobone\temp@}%
       \exptwoargs\ifin\list@macro@perso{\string#1}%
               {\print@idx{\leavevmode\hbox{\texttt{\string#1}}}% macro d�j� rencontr�e
               }
               {\xdef\list@macro@perso{\list@macro@perso\string#1}% premi�re apparition
               \print@idx{\leavevmode\hbox{\texttt{\string#1}${}^{{}\scriptscriptstyle\star{}}$}}%
               }%
       \index@macro@perso@i
}

\newcommand*\index@macro@perso@i[1][]{%
       \index[macros]{\temp@ @\texttt{\char92 \temp@}#1}%
       \restoreexpandmode
       \catcode`\@=\saved@at@catcode\relax
       \xspace
}

\edef\print@macro@list{\string\LaTeX\string\eTeX}

\let\list@indexentry\empty% liste des entr�es d'index

\def\left@@of#1#2{% dans la sc #1, garde ce qui est � gauche de #2
       \def\left@@of@i##1#2##2\@nil{\def#1{##1}}%
       \expandafter\left@@of@i#1#2\@nil
}

\newcommand\add@toindexentry[1]{% ajoute #1 � la liste d'entr�es ou pas
       \edef\temp@{\detokenize\expandafter{\string#1}}%
       \expandafter\left@@of\expandafter\temp@\string|% ne prend que ce qui est avant |
       \expandafter\left@@of\expandafter\temp@\string!% ne prend que ce qui est avant !
       \exptwoargs\ifin{\list@indexentry}{\temp@,}
               \relax
               {\xdef\list@indexentry{\list@indexentry\temp@, }}%
}

\newcommand\idx{\relax\makeatletter\@ifstar{\let\print@idx\@gobble\idx@}{\let\print@idx\@firstofone\idx@}}

\catcode`\W=3
\newcommand\idx@[2][]{%
       \saveexpandmode\expandarg
       \let\savedindex\index
       \expandafter\ifin\expandafter{\noindexlist}{W#2W}{\let\index\gobone}{}%
       \expandafter\if@controlsequence\expandafter{\firstto@nil#2\@nil}% si #2 est une s�quence de contr�le��*\firstto@nil�
               {\let\repeat\relax
               \add@toindexentry{#2}%
               \edef\temp@{\expandafter\gobone\string#2}%
               \long\edef\temp@a{\meaning#2}%
               \long\edef\temp@b{\string#2}%
               \let\xx@space\xspace
               \ifx\temp@a\temp@b% si #2 est une primitive
                       \expandafter\ifx\firstto@nil#2\@nil\ % #2 = \<espace> ?
                               \index{\char\number`#2 @\quitvmode\hbox to0pt {\hss${}^*$}\texttt{\char92 \char32 }#1}%
                               \print@idx{\texttt{\char92 \char32 }}%
                       \else
                               \index{\temp@ @\quitvmode\hbox to0pt {\hss${}^*$}\texttt{\char92 \temp@}#1}%
                               \print@idx{\texttt{\char92 \temp@}}%
                       \fi
               \else
                       \expandafter\expandafter\expandafter\ifempty
                       \expandafter\expandafter\expandafter{\expandafter\gobtwo\string#2}% si caract�re de contr�le
                               {\index{\char\number\expandafter`\temp@ "@@\texttt{\char92 \char\number\expandafter`\temp@}#1}%
                               \print@idx{\texttt{\char92 \temp@}}%
                               \let\xx@space\relax
                               }%
                               {\StrSubstitute\temp@{\string @}{\char64 }[\temp@]% remplace les @
                               \IfSubStr\print@macro@list{\string#2}%
                                       {\index{\temp@ @\protect#2#1}% si macro dans liste
                                       \print@idx{#2}%
                                       }%
                                       {\index{\temp@ @\texttt{\char92 \temp@}#1}%
                                       \print@idx{\texttt{\char92 \temp@}}%
                                       }%
                               }%
               \fi
               \restoreexpandmode
               \let\repeat\fi
               \makeatother
               \let\index\savedindex
               \xx@space
               }%
               {\restoreexpandmode
               \index{#2\ifx\@empty#1\@empty\else #1\fi}%
               \print@idx{#2}%
               \let\index\savedindex
               \makeatother
               }%
}
\catcode`\W=11

\newcommand\if@controlsequence[1]{%
       \begingroup
               \escapechar`\\
               \edef\first@char{\expandafter\firstto@nil\string#1\@nil}%�
               \edef\escape@char{\expandafter\firstto@nil\string\relax\@nil}%
               \ifx\first@char\escape@char
                       \endgroup\expandafter\firstoftwo
               \else
                       \endgroup\expandafter\secondoftwo
               \fi
}

\def\visiblespace{ }

% met en index un seul caract�re de la forme <char> ou \<char>
\newcommand\cidx{\relax\@ifstar{\let\print@idx\@gobble\cidx@}{\let\print@idx\@firstofone\cidx@}}
\newcommand\cidx@[2][]{%
       \if@controlsequence{#2}% si c'est une macro
               {\ifnum`#2=`\ % espace ?
                       \index{\char\number`#2 @\textvisiblespace#1}%
                       \add@toindexentry{ }%
                       \print@idx{\texttt{\char92 \char32 }}%
               \else
                       \index{\char\number`#2 @\texttt{\char\number`#2}#1}%
                       \expandafter\add@toindexentry\expandafter{\expandafter\char\number`#2}%
                       \print@idx{\texttt{\char\number`#2}}%
               \fi
               \xspace
               }
               {\StrSubstitute{#2}"{""}[\temp@@]%
               \index{\temp@@ @\texttt{\string#2}#1}%
               \add@toindexentry{#2}%
               }%
}

\def\idxdetokenize{\begingroup\catcode`\^12 \idxdetokenize@i}
\def\idxdetokenize@i#1{\endgroup\detokenize{#1}}
% met en index le second argument "d�tok�niz�"
\newcommand\verbidx{\begingroup\catcode`\^12 \@ifstar{\let\print@idx\@gobble\verbidx@}{\let\print@idx\@firstofone\verbidx@}}
\newcommand\verbidx@[2][]{%
       \index{#2@{\ttfamily\protect\idxdetokenize{#2}}#1}%
       \print@idx{{\ttfamily\idxdetokenize{#2}}}%
       \add@toindexentry{#2}%
       \endgroup
}

% met en index les primitives de test "\if...", "\else", "\fi"
\newcommand\tidx{\relax\@ifstar{\let\print@idx\@gobble\tidx@i}{\let\print@idx\@firstofone\tidx@i}}
\newcommand\tidx@i[2][]{% #2 est le nom de la primitive SANS le caract�re d'�chappement
       \index{#2@\quitvmode \hbox to0pt {\hss ${}^*$}\texttt{\char92 #2}#1}%
       \add@toindexentry{#2}%
       \print@idx{\texttt{\char92 #2}}%
}
%|                                fin index                                   |
%|____________________________________________________________________________|

\let\grandsaut\bigbreak
\newdimen\main@parindent

\usepackage[
       hyperindex    = false,
       plainpages    = true,
       pdfauthor     = {Christian~TELLECHEA},
       pdftitle      = {Apprendre~�~programmer~en~TeX},
       pdfsubject    = {Pr�sentation~des~concepts~de~base~et~apprentissage~de~la~programmation~en~langage~TeX},
       pdfcreator    = {LaTeX}
       ]{hyperref}

\@addtoreset{chapter}{part}

\makeatother
\begin{document}
\defactive�{\char19 \penalty10000 \FBguillspace\relax\ignorespaces}%
\defactive�{\unskip\penalty10000 \FBguillspace\relax\char20 }%
\pagestyle{scrheadings}%
\parindent=15pt
\parskip0pt plus.3pt
\hyphenation{cons-truire cons-truite cons-truites cons-truction cons-tructions cons-truit exem-ple exem-ples con-state con-stater con-sta-ta-tion}%
\widowpenalty=600
\clubpenalty=600
\interfootnotelinepenalty=10000
\csname main@parindent\endcsname=\parindent
\let\oldit=\it \let\it=\itshape
\let\oldbf=\bf \let\bf=\bfseries
\let\oldrm=\rm \let\rm=\normalfont
\let\oldtt\tt \let\tt=\ttfamily
\let\oldsc=\sc \let\sc=\scshape% �viter les avertissements d'obsolescence
\raggedbottom
\newcommand\drawbox[1]{%
       \leavevmode
       \begingroup
       \tikz\draw[fill,black,overlay](0.35pt,0pt)circle(1pt);%
       \fboxsep0pt \fboxrule0.2pt
       \kern-\fboxrule\fbox{#1}\kern-\fboxrule
       \endgroup}
\def\messageavert{message d'avertissement}
\startcontents[tableofcontents]
\startcontents[part]

% ____________________________________________________________________________
%|                                                                            |
%|                               D�but du livre                               |
%|                                                                            |
\frontmatter
\pagestyle{empty}
\null\pagebreak
\null\pagebreak
%%%%%%%%%%%% Page de titre %%%%%%%%%
\title{\huge Apprendre � programmer en \TeX{}}
\author{\small Christian \textsc{Tellechea}}
\date{\small Septembre 2014}
\def\largeurtext{85}%
\uppertitleback{%
       \leavevmode\null\hfill
       \vtop{%
               \hsize=.\largeurtext\textwidth
               \footnotesize
               \parskip=3pt
               Ce livre est � auto�dit� �, c'est-�-dire que la conception, les relectures et les corrections ont �t� faites par l'auteur. Malgr� le soin qui y a �t� apport�, des fautes et des erreurs peuvent encore exister.

               Toute erreur, omission ou toute proposition d'am�lioration peut �tre signal�e.\medbreak

               Email de l'auteur :\par
               \href{mailto:[email protected]}{\texttt{[email protected]}}\bigbreak

               D�p�t du code source, fichiers pdf et fichiers annexes :\par
               \href{https://framagit.org/unbonpetit/apprendre-a-programmer-en-tex/}{\texttt{https://framagit.org/unbonpetit/apprendre-a-programmer-en-tex/}}\bigbreak

               Remont�es de bugs, am�liorations :\par
               \href{https://framagit.org/unbonpetit/apprendre-a-programmer-en-tex/issues}{\texttt{https://framagit.org/unbonpetit/apprendre-a-programmer-en-tex/issues}}
               \vskip1.5cm

               Les codes et algorithmes figurant dans ce livre sont donn�s sans \emph{aucune garantie} en vue de leur utilisation dans le cadre d'une activit� professionnelle ou commerciale.
       }%
       \hfill\null
}

\lowertitleback{%
       \leavevmode\null\hfill
       \vtop{%
               \hsize=.\largeurtext\textwidth
               \small
               ISBN 978-2-9548602-0-6\medskip

               \textcopyright{} Christian \textsc{Tellechea}, 2014--2020\medskip

               \scriptsize
               R�vision \no2b, 20/12/2020\medskip

               Photo couverture \textcopyright{} Christian~\textsc{Tellechea}\par
               Photo 4\ieme{} couverture \textcopyright{} Willi~\textsc{Heidelbach}.
               \medbreak
               Le code source au format texte, ce fichier au format pdf qui en r�sulte apr�s compilation, les fichiers au format texte g�n�r�s par la compilation ainsi que les fichiers texte et pdf n�cessaires � la compilation sont plac�s sous la licence �LaTeX Project Public License Version 1.2� qui est consultable � l'adresse suivante \href{https://www.latex-project.org/lppl/lppl-1-2.txt}{\texttt{https://www.latex-project.org/lppl/lppl-1-2.txt}}
       }%
       \hfill\null
}

\dedication{%
       \vskip3cm
       \hfill
       \vtop{%
               \hsize=.47\linewidth
               \parindent=0pt
               \raggedleft\itshape\small
               Un langage de programmation est cens� �tre une fa�on conventionnelle de donner des ordres � un ordinateur. Il n'est pas cens� �tre obscur, bizarre et plein de pi�ges subtils (�a, ce sont les attributs de la magie).\medskip

               \normalfont Dave \textsc{Small}%
       }%
}

\extratitle{%
       \null\vskip0pt plus1fill
       \hfill
       \hbox{\Large\biolinum Apprendre � programmer en \TeX{}}%
       \hfill\null
       \vskip0pt plus3fill
       \null
}

\maketitle

\pagestyle{plain}\setcounter{page}{1}
\chapter*{Pr�face}

Il est d�j� bien difficile de maitriser \TeX{} comme langage de composition\ldots{} C'est un vrai d�fi que d'en connaitre suffisamment les m�andres pour l'utiliser comme langage de programmation\footnote{\TeX{} a �t� cr�� pour la composition et si son cr�ateur l'a �t� dot� de ce qu'il faut pour programmer, ce n'est pas par choix, mais parce qu'il a �t� oblig� de le faire (un peu � contrec\oe ur) !}. Et, c'est une mission quasi impossible que d'�crire un livre l�-dessus, j'en parle en connaissance de cause ! D'ailleurs, bien peu de choses existent sur le sujet. Non pas que les gens sachant programmer en \TeX{} soient rares, ils sont simplement assez sages et modestes pour ne pas s'embarquer dans une telle gal�re. Inconscient, insouciant et trop s�r de moi, j'ai commenc� � �crire sans mesurer les difficult�s auxquelles j'allais me heurter. Je ne sais toujours pas quelle folie m'a pouss� � poursuivre cette aventure jusqu'au bout. M�me si un peu de vanit� a certainement jou� un r�le, ma motivation n'a jamais �t� de montrer que � moi, je peux �; il ne s'agit pas d'un p�ch� d'orgueil. Le but poursuivi, moteur plus fort que les difficult�s rencontr�es au cours de cette aventure, a �t� d'aider ceux qui, comme moi lorsque j'�tais d�butant en programmation \TeX, restent devant un code �crit en \TeX{} comme devant un texte en chinois ancien : plong�s dans un abime d'incompr�hension.

\Qu iconque connait un peu \TeX{} a d� sourire en lisant la citation de Dave~\textsc{Small}. Et a d� se dire qu'avec \TeX{} bien plus qu'avec d'autres langages, on allait forc�ment parler de magie noire � un moment ou � un autre ! Car il est vrai que \TeX{} est un langage difficile, tortueux et r�put� comme tel. On ne compte plus ceux qui font tout pour ne pas s'y frotter, ceux qui le ha�ssent ou le rejettent ni ceux qui, bien que l'utilisant, se traitent de fous tant des choses apparemment simples sont en r�alit� compliqu�es. \TeX{} est bourr� de d�fauts, collectionne les lacunes, a une syntaxe � coucher dehors tant elle est irr�guli�re, mais malgr� tout cela, on se prend � l'appr�cier un peu comme on pourrait appr�cier les d�fauts d'un ami de longue date, taciturne et bourru. Tout comme cet ami pourrait envier certains c�t�s aux � nouveaux communicants � dont nous sommes d�sormais entour�s, \TeX{} ne soutient pas non plus la comparaison avec les langages modernes. Mais, l'utiliser pour programmer procure un plaisir certain ainsi qu'une sensation de libert� et de cr�ativit� qu'on ne retrouve que dans une moindre mesure avec les langages de programmation r�cents.

J'invite donc mon lecteur, arm� de patience et de pers�v�rance, � entreprendre ce p�riple qui s'annonce ardu, mais riche de nouveaut�s et d'originalit�. La meilleure chose que je lui souhaite est d'arriver � ses fins et par l� m�me, atteindre aussi le but dans lequel ce livre a �t� �crit : acqu�rir une autonomie dans la programmation en \TeX. Ce livre, qui n'est qu'une simple introduction � la programmation en \TeX, sera peut-�tre un d�part pour de nouveaux horizons qui, apr�s beaucoup de pratique et sans utilisation de magie noire --~c'est garanti !~--, le m�neront, qui sait, � devenir un \TeX gourou\ldots

% ____________________________________________________________________________
%|                                                                            |
%|                             Table des mati�res                             |
%|                                                                            |
\cleardoublepage
%%%%%%%%% Table des mati�res %%%%%%%
\begingroup
       \huge\centering
       {\null\vspace{2cm}\bfseries\scshape Table des mati�res}\par
       {\Huge\bfseries\libLegacyGlyph{uniE007}}\bigbreak
       \normalfont\normalsize
       \makeatletter
       \renewcommand*\l@chapter{\@dottedtocline{0}{0em}{1.5em}}
       \printcontents[tableofcontents]{sommaire-}{-1}{\setcounter{tocdepth}{2}}
       \clearpage
\endgroup
%|                                                                            |
%|                           Fin table des mati�res                           |
%|____________________________________________________________________________|

\pagestyle{scrheadings}
\mainmatter

\chapter*{Conventions adopt�es dans ce livre}
\addcontentsline{toc}{part}{Conventions adopt�es dans ce livre}

\subsubsection{Les codes}
Par souci de p�dagogie, les codes sont tr�s nombreux. Ils sont pr�sent�s de telle sorte que le code pr�c�de l'affichage qu'il g�n�re. En voici un, le premier d'une longue s�rie :

\showcode/Voici le code en \TeX{} du premier exemple.% ceci est un commentaire

On peut observer l'affichage qu'il produit juste au-dessous !/%

Sauf pour des cas tr�s exceptionnels qui seront signal�s, il ne peut y avoir de �triche� sur l'affichage : il est tr�s exactement le r�sultat du code qui se trouve au-dessus. En effet, les codes sont tap�s \emph{une seule fois} dans le code source de ce livre. Une macro est charg�e de stocker ce code pour ensuite fonctionner en deux temps. Elle l'affiche tel quel dans la partie haute du cadre puis laisse \TeX{} le compiler et afficher le r�sultat dans la partie basse.

Les codes donn�s produisent donc les r�sultats affich�s, mais le lecteur doit garder en t�te les limitations suivantes :

\begin{itemize}
       \item malgr� les relectures effectu�es sur chaque code, ils ne sont pas garantis sans �bogue�. Certains bogues �tant particuli�rement difficiles � d�busquer, il serait m�me tr�s �tonnant que certains n'en contiennent pas !
       \item dans la plupart des cas, les codes donn�s ne sont qu'une fa�on de faire \emph{parmi beaucoup d'autres}, le nombre d'alternatives tendant � augmenter avec la complexit� de la t�che � ex�cuter. Ces codes sont donc � consid�rer comme \emph{une} solution et non pas comme \emph{la} solution. Ils n'ont donc pas valeur de m�thode absolue qui serait meilleure que toute autre;
       \item ils ne fonctionnent que pour un certain domaine de validit� (souvent implicite) des arguments de leurs macros, car �largir ce domaine suppose des complications qu'il est long et fastidieux de programmer. On peut donc toujours trouver des cas plus ou moins sp�ciaux o� les arguments contiennent des choses qui feront �planter� une macro.

       Par exemple, si une macro attend un nombre entier et qu'on lui donne la lettre �a� comme argument, \TeX{} va protester avec l'erreur �\texttt{missing number}�. Par ailleurs, des caract�res sp�ciaux comme �\verb|#|� seul, �\verb|%|�, etc. vont in�vitablement provoquer des plantages s'ils sont �crits dans les arguments des macros. Sauf dans les cas o� ces caract�res sp�ciaux sont g�r�s, les macros attendent des arguments �gentils�, c'est-�-dire constitu�s de caract�res ayant un code de cat�gorie de 10, 11 ou 12 (voir page~\pageref{catcode.table});
       \item les codes propos�s ne sont pas toujours \emph{optimis�s}, c'est-�-dire que leur vitesse d'ex�cution tout comme la consommation de m�moire qu'ils requi�rent peuvent �tre am�lior�es. Ils r�pondent avant tout � deux contraintes, celle d'illustrer la notion qui est en train d'�tre abord�e tout en utilisant des notions pr�c�demment vues et celle de ne pas inutilement compliquer le code.
\end{itemize}

J'invite le lecteur � \emph{lire} les codes propos�s, m�me s'ils sont r�barbatifs. Lire n'est pas survoler ! Lorsque les codes deviennent assez complexes, il faut vraiment faire un effort mental important et se plonger dedans afin de comprendre comment ils fonctionnent. Les commentaires ins�r�s dans le code, toujours tr�s nombreux, fournissent une aide pour cela, mais la gymnastique mentale consistant � analyser l'enchainement des instructions et comprendre comment �voluent les arguments des macros reste n�cessaire.

\subsubsection{Les exercices}
Les exercices, �galement en grand nombre et de difficult� variable, sont souvent propos�s au lecteur au fur et � mesure que de nouvelles notions sont pr�sent�es. Ils sont pr�c�d�s d'un �{\footnotesize\rule{1.25ex}{1.25ex}}� et imm�diatement suivis de leur solution, choix discutable, mais qui s'est impos�. Voici � ce propos le premier exercice :

\begin{exercice}
\Qu el argument principal peut-on trouver pour justifier que les exercices soient imm�diatement suivis de la solution ?

\solution
Se d�cider a �t� difficile, mais qu'y a-t-il de plus lassant que de passer son temps � tourner les pages pour aller d�busquer � la fin du livre la solution d'un exercice que, bien souvent, on n'arrive pas � r�soudre ? Ou qu'on ne \emph{souhaite} pas r�soudre ! Sur ce point, l'exp�rience un peu p�nible du \TeX book (que vous avez bien s�r d�j� lu et relu !) a �t� d�cisive et m'a pouss� � pr�senter les choses diff�remment. Il me semble que le lecteur, suppos� adulte et ayant un certain contr�le de lui-m�me, peut se retenir de lire la solution s'il souhaite vraiment chercher un exercice.
\end{exercice}

\subsubsection{�l�ments de code}
Les chevrons ''$\lcodedelim$`` et ''$\rcodedelim$`` ont vocation � symboliser des �l�ments dont la nature est exprim�e par les mots se trouvant entre ces chevrons. Ainsi, \verb|<nombre>| est cens� repr�senter\ldots{} un nombre ! Selon la m�me notation, on aurait \verb|\<macro>|, \verb|<texte>|, \verb|<code>| (pour du code source en \TeX{}), \verb|<car>| (pour un caract�re), \verb|<dimension>|, etc.
\grandsaut

Un espace dans le code source peut �tre mis en exergue, soit parce qu'il rev�t une importance particuli�re, soit parce sa pr�sence est importante et qu'il doit �tre clairement �tre visible. Dans ces cas, il est not� �\verb*| |�.

Un caract�re isol� peut parfois �tre encadr� pour qu'il soit ais�ment identifiable, comme l'apostrophe inverse �{\def\boxtokensep{0.5pt}\boxtoken `}�.

Lorsqu'il peut y avoir ambig�it� sur les caract�res composant le nom d'une commande ou bien parce que nom contient des caract�res inhabituels, le nom est encadr� comme dans �\hbox{\verb|\|\fboxsep1pt \fbox{\ttfamily a\string_1\string\b7}}� (car une commande peut tout � fait porter un nom pareil !).

\subsubsection{Les macros propres � ce livre}
Tout au long de ce livre, des macros sont d�finies dans des codes ou dans des exercices. Lorsqu'elles sont d�finies, elles sont suivies du signe �$\star$� mis en exposant comme dans \verb|\gobone|${}^{{}\star{}}$. Elles disposent d'un index � part (voir page~\pageref{index.macros}) o� l'on peut ais�ment trouver le num�ro de page o� chacune d'entre elles a �t� mentionn�e. Lorsqu'elles sont mentionn�es dans l'index g�n�ral, elles sont �galement suivies de �$\star$�.

\subsubsection{Anglicismes}
Si � mon grand regret l'anglais --~que dis-je, le \emph{globish} !~-- tend � s'imposer comme langue universelle de communication entre personnes ne parlant pas la m�me langue, il s'est depuis longtemps impos� comme langue en programmation. Il est en effet ind�niable que les mots-cl�s de presque tous les langages de programmation sont en anglais. Ceci a conduit � employer des mots anglais pour d�signer des notions couramment utilis�es dans le monde de la programmation. J'ai donc fait le choix facile, pour quelques mots, d'utiliser la version anglaise.

\begin{centrage}
\footnotesize
\begin{tabular}{>\itshape llp{0.55\linewidth}}\\\hline
       \normalfont Anglais&Fran�ais&Signification\\\hline
       \idx{token}&entit� lexicale&s�quence d'un ou plusieurs caract�res du code source reconnue et assimil�e par \TeX{} comme un �l�ment indivisible selon les r�gles de l'analyseur lexical qui seront expos�es dans ce livre.\\
       tokenization&segmentation&s'applique � une portion du code source : transformation des caract�res du code source en tokens.\\
       catcode&code de cat�gorie&s'applique � un token : entier sur 4 bits (0 � 15) affect� � un token lorsqu'il est lu par \TeX.\\
       \idx{package}&extension&mot g�n�rique signifiant � fichier externe permettant d'accroitre les possibilit�s de \TeX{} �. Bien souvent, il s'agit de code source mettant � disposition des macros permettant de r�aliser des t�ches complexes.\\\hline
\end{tabular}
\end{centrage}

\subsubsection{Les r�gles}
Au fur et � mesure de la progression, des r�gles pr�cisant la fa�on de fonctionner de \TeX{} sont inscrites dans des cadres sur fond gris. Toutes ces r�gles sont reprises en annexe � partir de la page~\pageref{recapregle}.

\subsubsection{Orthographe rectifi�e}
Lorsque j'ai vu la moue un peu dubitative des rares personnes ayant lu quelques passages de ce livre, j'y ai vu l'embarras de ceux qui, me d�couvrant incapable d'�crire quelques phrases sans faute, se pr�paraient � me faire des remarques sur mon orthographe fautive.

J'ai fait le choix, comme l'indique le logo ci-dessous, d'utiliser l'orthographe rectifi�e de la r�forme de 1990.

\begin{centrage}
       \includegraphics[scale=0.3333]{vignette.png}
\end{centrage}

Par cons�quent, la phrase � \emph{nous sommes surs que la boite va disparaitre}� est orthographiquement correcte. Il ne manque aucun accent circonflexe, m�me s'il en fallait trois avant la r�forme. \Qu e l'orthographe rectifi�e soit encore actuellement consid�r�e comme fautive par la majorit� des personnes me laisse un peu interrogatif. Malgr� plus de deux d�cennies pendant lesquelles elle a �t� \emph{recommand�e}, le fait qu'elle soit si peu reconnue et pratiquement absente de l'enseignement ne s'explique pour moi que par le rapport excessivement rigide et crisp� que nous entretenons avec notre orthographe.

Bien �videmment, ce livre �tant 100\% \emph{fait-maison}, je ne peux le garantir exempt de coquilles, d'accords fautifs ou de lourdeurs. Je pr�sente d'ores et d�j� mes excuses � mes lecteurs pour les d�sagr�ments que cela leur procurera.
%|                                                                            |
%|                             Fin d�but du livre                             |
%|____________________________________________________________________________|


% ____________________________________________________________________________
%|                                                                            |
%|                                Introduction                                |
%|                                                                            |
\addpart{Introduction}
\chapter{\TeX{}, la brute et le truand}
\section{Les sp�cificit�s de \TeX}
Le programme \texttt{tex} est con�u pour lire du code source (le plus souvent enregistr� dans un fichier de type �texte�) puis �compiler� ce code afin de produire un document affichable disponible dans un fichier de type \texttt{dvi}\idx*{fichier!dvi}. Un tel programme, transformant du code source en document affichable, est appel� �\emph{\idx{moteur}}\footnote{On dit aussi parfois �\emph{compilateur}�.}�. Le langage \TeX{}\footnote{Il ne faut pas confondre le \emph{moteur} \texttt{tex}\idx*{moteur!tex} qui est ex�cut� par un ordinateur et le \emph{langage} \TeX{}. Ce langage met � disposition des commandes pour produire un document, mais aussi des commandes pour \emph{programmer}. C'est d'ailleurs le but de ce livre que d'expliquer comment utiliser ces derni�res.} met � disposition des commandes qui sont appel�es \emph{\idx{primitive}s}, tout en permettant de \emph{d�finir} d'autres commandes, appel�es �\emph{macros-instructions}� ou �\emph{macros}�. Compte tenu de leur puissance, ces derni�res sont d'un emploi extr�mement courant et sont donc pratiquement indispensables. Elles peuvent �tre d�finies par l'utilisateur � l'int�rieur m�me du code source, mais peuvent aussi �tre contenues dans un fichier externe appel� extension ou �\emph{\idx{package}}� qui sera lu � un endroit du code source choisi par l'utilisateur. Derni�re possibilit�, des macros peuvent �galement �tre pr�compil�es pour �tre incorpor�es dans un ex�cutable appel� �\emph{\idx{format}}� qui embarque le langage \TeX{} dans sa totalit� ainsi que des macros pr�compil�es. Ainsi, lorsqu'on lance l'ex�cutable d'un format, ces macros sont d�j� d�finies avant que le d�but du code source ne soit lu.

Les formats les plus connus et les plus utilis�s\footnote{On ne peut pas vraiment parler de fr�quence d'utilisation des formats les plus � c�l�bres �, car n'importe qui peut se construire son propre \idx{format} � la carte. La man\oe uvre � suivre ne sera pas d�crite dans ce livre.} sont :% TODO : v�rifier qu'un saut de page n'a pas lieu ici

\begin{itemize}
       \item plain-\TeX\idx*{format!plain-\TeX}, dont l'ex�cutable est �\texttt{tex}�, o� les macros �\texttt{plain}� ont �t� d�finies par l'auteur de \TeX{} lui-m�me. Il est donc � noter que lorsqu'on lance le programme \texttt{tex}, en plus du langage \TeX{} \emph{nu}, on dispose aussi de toutes les macros de \texttt{plain};
       \item \LaTeX\idx*{format!\LaTeX}, dont l'ex�cutable est �\texttt{latex}�, qui est un recueil de macros, �crites et mises en coh�rence � l'origine par \idx*{Lamport Leslie}Leslie~\textsc{Lamport} et dont le but est de fournir des macros de haut niveau pour la composition;
       \item Con\TeX t\idx*{format!Con\TeX t} qui est un peu � part des deux pr�c�dents en ceci qu'il n'est pas bas� sur le moteur \texttt{tex}\idx*{moteur!tex} mais sur un autre moteur permettant l'acc�s au langage \emph{\idx{lua}};
       \item pour m�moire, en voici de tr�s peu connus ou tr�s anciens, mais qui ont le m�rite d'exister : \texttt{phyzzx}, \texttt{psizzl}, \texttt{Lollipop} et \texttt{TeXsis}. Le plus original de la bande est sans doute \texttt{StarTeX} qui a une approche tr�s �loign�e de tous les autres puisque la syntaxe des commandes se rapproche au plus pr�s de celle de l'\texttt{HTML} !
\end{itemize}

Le langage \TeX{} et ses formats sont r�put�s produire des documents de grande qualit� typographique, mais \TeX{} est vieux. Son concepteur, \idx*{Knuth Donald}Donald~\textsc{Knuth}, l'a publi� en 1982\footnote{Une version plus r�cente �\TeX90� a �t� publi�e en 1990 o� de nouvelles primitives ont �t� incorpor�es et o� la lecture du code est d�sormais sur 8 bits au lieu de 7 pour �\TeX82�.}, �poque o� aucun des langages � modernes � n'existait encore. Pour le programmer, il a utilis� un vieux langage s'il en est, le Pascal. \TeX{} est assur�ment tr�s stable, probablement exempt de bug, mais ind�niablement \emph{tr�s vieux} � l'�chelle du temps informatique. On peut d'ailleurs s'�tonner qu'entre 1982 et le d�but des ann�es 2000, une aussi longue p�riode se soit �coul�e sans �volution majeure. Certes, entre temps, un nouveau moteur �\eTeX\idx*{moteur!etex}� a vu le jour o� de nouvelles primitives ont ajout� des fonctionnalit�s bien pratiques qui n'existaient pas dans le langage \TeX{} initial. Plus r�cemment encore, le moteur �pdf\TeX\idx*{moteur!pdftex}� a �t� �crit par H�n Th\'{�} \textsc{Th�nh}\idx*{H�n Th� Th�nh} et de nouvelles fonctionnalit�s ont �t� ajout�es, tout en conservant celles de \eTeX\idx*{moteur!etex}. Mais ce qui fait la particularit� de pdf\TeX\idx*{moteur!pdftex} est qu'il est capable de produire \emph{directement} un fichier \verb|pdf|\idx*{fichier!pdf} � partir du code source sans passer par le fichier \texttt{dvi} jusqu'alors incontournable.
\grandsaut

Au-del� de son �ge, mais peut-�tre en sont-ce des cons�quences, \TeX{} a deux particularit�s qui le rendent peu attractif, voire carr�ment repoussant pour beaucoup de personnes qui s'y essaient.

Tout d'abord, la fa�on intrins�que que \TeX{} a de fonctionner, certes tr�s originale, ne ressemble pas � celle qui est devenue la norme dans la plupart des langages de programmation. Ceci est \emph{extr�mement} d�routant et conduit bien souvent � une incompr�hension puis un rejet de ce langage, m�me pour des programmeurs avertis. Car avec \TeX{}, les m�thodes de programmation changent et donc, c'est aussi la fa�on de penser un algorithme qui change !

Pour r�sumer � l'extr�me, \TeX{} est un langage \emph{de macros}, c'est-�-dire que les appels aux macros provoquent le remplacement de ces macros (et de leurs arguments) par un nouveau code. Ce code --~ou � \idx{texte de remplacement} �~-- est celui qui a �t� donn� � la macro lors de sa d�finition. De plus, et c'est une originalit� suppl�mentaire en \TeX, lorsqu'on d�finit une macro, non seulement on d�finit son texte de remplacement, mais on d�finit \emph{aussi} la syntaxe avec laquelle elle devra �tre appel�e. Enfin, et c'est l� un des points les plus difficiles, \TeX{} ne proc�de � \emph{aucune �valuation}, ni du \idx{texte de remplacement} lors de la d�finition d'une macro, ni des arguments qui lui sont donn�s lorsqu'elle est appel�e.

Voici un exemple qui peut illustrer cette absence d'�valuation. Pour comprendre le probl�me, tenons-nous � l'�cart de la syntaxe de \TeX{} o� les commandes doivent commencer par �\verb|\|� et les arguments doivent �tre entre accolades. Adoptons plut�t une syntaxe �g�n�rique� o� les commandes sont �crites normalement et o� les arguments se trouvent entre parenth�ses. Imaginons qu'une macro �\verb|left|� ait �t� cr��e et qu'elle admette deux arguments. Le premier de type chaine de caract�res alphanum�riques, not� �\verb|A|� et le second de type entier, not� �\verb|i|� : le r�sultat de cette macro est constitu� par ce qui se trouve � gauche du caract�re \no\verb|i| de la chaine \verb|A|. Par exemple, le code :

\centrecode-left(bonjour)(4)-

\noindent donnerait les caract�res se trouvant � gauche de 4\ieme{} lettre, c'est-�-dire �\verb|bon|�.

De la m�me fa�on, admettons qu'il existe aussi une macro �\verb|right|� qui elle, renvoie ce qui se trouve � droite du caract�re \no\verb|i| dans la chaine \verb|A|. Et donc :

\centrecode-right(bonjour)(4)-

\noindent donnerait les caract�res �\verb|our|�.

Voici maintenant un raisonnement extr�mement r�pandu en programmation et c'est d'ailleurs le c\oe ur du probl�me. N'importe quel programmeur pense --~avec raison~-- que pour isoler ce qui se trouve entre les caract�res \no2 et \no5 dans la chaine �\verb|bonjour|� (c'est-�-dire les caract�res �\verb|nj|�), il suffit d'�crire :

\centrecode|right(left(bonjour)(5))(2)|

Ce raisonnement suppose que les arguments de \verb|right|--~ici en particulier le premier~-- ont
�t� �valu�s \emph{avant} que la macro n'entre en jeu. Ce premier argument qui est �\verb|left(bonjour)(5)|� serait donc remplac� par son r�sultat �\verb|bonj|� et finalement, apr�s cette �valuation, tout se passe comme si on avait l'appel :

\centrecode|right(bonj)(2)|

\noindent Or, cette �valuation n'a pas lieu avec \TeX{} ! Essayons de nouveau d'appr�hender ce code, mais adoptons un esprit \TeX ien :

\centrecode|right(left(bonjour)(5))(2)|

\noindent \TeX{} ex�cute le code de gauche � droite donc, lorsqu'il ex�cute la macro \verb|right|, il va lui transmettre ses deux arguments qui sont �\verb|left(bonjour)(5)|� et �\verb|2|�. Et donc, les caract�res renvoy�s seront tout ce qui se trouve � droite de la 2\ieme{} lettre du premier argument, c'est-�-dire �\verb|ft(bonjour)(5)|�.

Le simple fait que le premier argument ne soit pas �valu� conduit non seulement � un r�sultat radicalement diff�rent, mais surtout implique que si l'on souhaite un comportement �normal�, c'est au programmeur d'int�grer � la macro un m�canisme qui se charge d'�valuer cet argument avant que le code utile de la macro ne traite le r�sultat. Pour ceux qui viennent d'autres langages, cette charge de travail suppl�mentaire est souvent ressentie comme une corv�e, sans compter que le code s'en trouve alourdi et donc moins lisible.

Une bonne partie des probl�mes que rencontrent les personnes non habitu�es � \TeX{} vient de la confusion qu'ils font entre :
\begin{itemize}
       \item l'affichage qui r�sulte d'un code;
       \item ce code lorsqu'il est dans l'argument d'une macro.
\end{itemize}

L'explication de cette confusion tient au fait que la plupart des langages ont un m�canisme --~appel� �\idx{pr�processeur}�~-- qui \emph{lit, analyse, �value puis remplace les arguments par leurs r�sultats}, et ce avant que la macro ne soit ex�cut�e. Avec \TeX{}, ce pr�processeur est r�duit � sa plus simple expression : il ne fait que \emph{lire} et \emph{tokenizer} cet argument\footnote{Dans ce cas, on a affaire � un pr�processeur de bas niveau, le plus bas qui soit, et on parle de �pr�processeur lexical�.}.

\Qu elle que soit l'affinit� --~ou l'adoration~-- que l'on �prouve envers \TeX{}, on est bien oblig� de reconnaitre que cette fa�on de faire n'est pas \emph{naturelle}. Car notre cerveau est lui aussi dot� d'un \idx{pr�processeur} intelligent qui agit de fa�on semblable � celui des langages de programmation �normaux�. Par exemple, n'apprend-on pas en math�matiques que :

\[\text{si }f(x)=x^2\text{\quad alors\quad}f(2\times3-1)=25\]

\noindent Avant tout calcul concernant la fonction $f$, ne proc�de-t-on pas spontan�ment � l'�valuation de l'argument �$2\times3-1$� pour le remplacer par le r�sultat, c'est-�-dire le nombre $5$ ? Ce faisant, ne proc�de-t-on pas comme les langages de programmation modernes qui, eux aussi, �valuent les arguments des macros ?

Tout ceci conduit donc � une premi�re r�gle, probablement une des plus importantes de toutes :

\label{regle.argument}\begin{regle}
Si un code quelconque, notons-le \hbox{\verb|<|$x$\verb|>|}, produit un affichage \hbox{\verb|<|$y$\verb|>|} alors, sauf cas tr�s particulier, il n'est pas �quivalent d'�crire \hbox{\verb|<|$x$\verb|>|} ou \hbox{\verb|<|$y$\verb|>|} dans l'argument d'une macro.
\end{regle}
\grandsaut

L'autre inconv�nient de \TeX{} qui rebute les personnes habitu�es � des langages plus modernes est que, pris comme un langage de programmation, \TeX{} est dot� du \emph{strict minimum} ! Pour parler avec mod�ration, l'\emph{extr�me minimalisme}\footnote{D'autres, moins bienveillants, parleraient de �pauvret�.} de ce langage est totalement d�routant, car toutes les facilit�s auxquelles les langages modernes nous ont habitu�es depuis longtemps ne sont tout simplement pas impl�ment�es dans \TeX{}. On ne parle pas ici de structures �volu�es comme de pointeurs ou pire, de programmation orient�e objet. Non, on parle de structures de contr�le des plus \emph{basiques}. Il va falloir renoncer � la cr�ation de variables typ�es, aux op�rateurs logiques bien pratiques lors des tests (�\texttt{or}�, �\texttt{and}�, �\texttt{not}�), aux boucles (�\texttt{for}�, �\texttt{while}�, etc.), aux tableaux, aux nombres d�cimaux et aux op�rations scientifiques, ainsi qu'� beaucoup d'autres choses. En \TeX{}, on doit se contenter de r�cursivit�, de tests simples, de nombres entiers et des quatre op�rations arithm�tiques, et encore avec quelques limitations pour ces derni�res. Et si l'on veut profiter de structures plus �volu�es, il faut les programmer soi-m�me ! Heureusement, cela est toujours possible, car \TeX{}, dans son minimalisme, a �t� dot� de tout ce qu'il faut pour construire n'importe quel algorithme, aussi complexe soit-il. On qualifie un tel langage de �complet�. On aborde d'ailleurs dans ce livre la programmation de structures de contr�le plus �volu�es que celles directement accessibles par \TeX.

�videmment, lorsqu'on programme en \TeX{}, on ne se trouve pas au niveau de l'assembleur\footnote{Le �langage machine� est le langage de plus bas niveau qui soit, c'est-�-dire le moins compr�hensible par un humain : ce sont des commandes directement compr�hensibles par le microprocesseur qui sont des assemblages de bits ou si l'on pr�f�re, des suites de 0 et de 1.

Ces suites de bits, traduites en instructions ais�ment m�morisables par un humain, constituent le langage �assembleur�.} car tout de m�me, \TeX{} est un langage de bien plus haut niveau. En revanche, ce qui est certain, c'est qu'on programme � un niveau beaucoup plus bas que celui de tous les langages actuels. Cela oblige donc � revenir aux fondamentaux de la programmation, et ce retour aux sources est parfois v�cu comme une r�gression par les personnes venant d'autres langages. Pourtant, contrairement � ce que l'on peut penser, revenir aux concepts de base de la programmation aide � �laborer des algorithmes plus efficaces et mieux construits (ceci �tant vrai quel que soit le langage utilis�), oblige � mieux comprendre les m�thodes sous-jacentes aux structures complexes et en fin de compte, fait accomplir des progr�s en algorithmique tout comme en compr�hension de la fa�on dont fonctionne un ordinateur.

\section{La rel�ve}
Ces contraintes intrins�ques � \TeX{} font que, petit � petit, de plus en plus de gens gravitant autour de la sph�re \TeX{} --~des utilisateurs de \LaTeX{} pour la plupart~-- ont admis que ce langage �tait devenu obsol�te, tant pour la composition que pour la programmation. � leurs yeux, il devenait convenable, sinon de le cacher aux yeux des utilisateurs, au moins de proposer des alternatives consid�r�es comme viables.

Le probl�me est que le \idx[!\LaTeX]{format} \texttt{latex} offre une collection de macros pr�compil�es appel�es \LaTeX{} dont le but est de proposer des commandes de haut niveau pour la composition mais h�las, \emph{presque rien} pour la programmation ! Pour pallier ce manque, les utilisateurs de \LaTeX{} se sont vus proposer des extensions sp�cialis�es qui rendent la vie du programmeur plus simple et qui mettent � disposition des commandes permettant de cr�er facilement des boucles ou autres structures de contr�le de plus haut niveau.

Le progr�s que cela repr�sente est consid�rable, car la facilit� d'utilisation est au rendez-vous. Il devient ainsi \emph{tr�s} facile de faire appel � une boucle de type �\verb|for|�. Bien s�r, chaque \idx{package} a sa propre syntaxe et ses propres instructions. Mais finalement, beaucoup d'entre eux ont une intersection non vide qui est la mise � disposition de commandes sur les boucles et les tests notamment. �tant donn� le grand nombre de packages disponibles pour la seule programmation, il est presque impossible de connaitre les instructions de tous les packages. Le travers que cela cr�� est que certains utilisateurs deviennent totalement d�pendants d'un package auquel ils sont habitu�s, quitte � ce que cela confine parfois � l'absurde. Un des exemples les plus frappants est le package �ti\textit kz� dont le but est de proposer des commandes de tr�s haut niveau pour faire des dessins vectoriels. C'est un package d'une taille absolument gigantesque qui compte � peu pr�s \numprint{300000}\footnote{� comparer avec les \numprint{8000} lignes du code de \LaTeX{} !} lignes de code, �crit en \TeX{} et en perp�tuelle �volution et qui propose, en plus de commandes de dessin vectoriel, des outils qui facilitent la vie en programmation. Bien entendu, on y trouve des commandes qui permettent de construire des boucles. L'absurde de la situation est que parfois, certains utilisateurs d�pendants de ti\textit kz et incapables de programmer par ignorance des commandes de \TeX{}, en viennent � charger un \idx{package} aussi volumineux pour ne se servir que d'une instruction en vue de cr�er une boucle, le tout en dehors de tout contexte de dessin. Certes, la solution fonctionne, mais l'efficacit� n'est pas vraiment optimale.
\grandsaut

Le projet qui est actuellement en pleine phase d'exp�rimentation est \LaTeX3\index{format!\LaTeX3|(}. Il s'agit d'un projet qui rel�ve un d�fi tr�s ambitieux, celui de remplacer et d'am�liorer l'actuelle version de \LaTeX. Ce projet, en maturation intense depuis de nombreuses ann�es et anim� par une �quipe de codeurs tr�s exp�riment�s, arrive actuellement � un stade o� des pans entiers, bien que toujours en �volution, deviennent utilisables. Le pan qui �merge en ce moment est carr�ment un nouveau langage de programmation enti�rement �crit en \TeX{} ! Comme \TeX{} est un langage complet, tout est possible, m�me le plus inattendu ! Ce nouveau langage de programmation offre d'innombrables possibilit�s que \TeX{} ne proposait pas, certaines extr�mement ardues � programmer. De plus, les auteurs ont essay� autant qu'ils le pouvaient d'inclure un \idx{pr�processeur}, actionnable � volont� et agissant sur les arguments des macros individuellement. Un code �crit dans ce nouveau langage devient donc beaucoup plus �pur� et lisible que du code \TeX{}, autant par la pr�sence de ce \idx{pr�processeur} que par l'extraordinaire diversit� des macros mises � disposition. Celles-ci couvrent des domaines aussi vari�s que :

\begin{itemize}
       \item toutes les structures de contr�le basiques : tests, boucles;
       \item nombres d�cimaux en virgule fixe ou flottante et les op�rations arithm�tiques et scientifiques sur ces nombres ;
       \item recherche, remplacement dans une chaine de caract�res avec la possibilit� de faire appel � des crit�res dont la syntaxe est proche de celle des �expressions r�guli�res\footnote{Une expression r�guli�re est une suite de signes, appel�s �motif�, qui d�crit selon une syntaxe pr�cise des r�gles auxquelles doit satisfaire une chaine de caract�re lors d'une recherche.

       Un livre entier serait � peine suffisant pour explorer le monde des expressions r�guli�res. Ce qu'il faut savoir est qu'elles sont tr�s largement utilis�es autant pour leur compacit� que pour leur puissance.}�;
       \item tri de donn�es ;
       \item etc.
\end{itemize}

Le revers de la m�daille est qu'il faut apprendre ce nouveau langage dont la syntaxe est suffisamment �loign�e de celle de \TeX{} pour d�router, voire rebuter un grand nombre d'utilisateurs habitu�s depuis des ann�es voire des d�cennies � celle de \TeX{} ou \LaTeX. Ce nouveau langage se veut en effet beaucoup plus r�gulier que ne l'est \TeX, � tel point qu'il peut apparaitre fade, aseptis� et domestiqu� en regard de l'original qui, par ses d�fauts un peu folkloriques, peut �tre ressenti comme davantage original et attachant. Le point le plus discutable est que \TeX{}, le langage sous-jacent, est volontairement rendu totalement invisible pour l'utilisateur final de \LaTeX3, toujours selon la volont� que \TeX{} doit �tre cach� � l'utilisateur, car jug� trop difficile, obsol�te et contraignant. \LaTeX3 cr�� finalement une dichotomie entre les utilisateurs. Les uns, pragmatiques, d�sireux de savoir et pr�ts � apprendre un nouveau langage, se moquent �perdument du \emph{vrai} langage qui se trouve sous cette �couche�, trop contents d'avoir enfin � leur disposition un langage au comportement quasi �normal�. Les autres, par curiosit� intellectuelle et par d�sir de comprendre, ou tout simplement par rejet de \LaTeX3, n'y adh�reront pas et pr�f�reront ouvrir le capot afin de voir ce qui se joue en coulisses.

Il va sans dire que ces derniers devront, si ce n'est d�j� fait, se mettre � \TeX{} et que les autres doivent sans tarder lire la documentation de \LaTeX3\index{format!\LaTeX3|)}.

\section{La r�volution}
Mais que ces utilisateurs ne se ruent pas trop vite sur \LaTeX3, car il y a autre chose. Depuis l'ann�e 2005, un nouveau moteur est en train de voir le jour. Il s'agit de lua\TeX{}\idx*[|(]{moteur!luatex}, un moteur o� bien s�r le langage \TeX{} est toujours accessible, mais o� est �galement rendu possible l'acc�s au langage �\texttt{lua}�. Ce langage, cr�� en 1993 a justement �t� �crit pour �tre embarqu� dans des applications pour en �tendre les possibilit�s. Lua\idx*{lua} est un langage \emph{interpr�t�} mais surtout, il poss�de tout ce que \TeX{} n'a pas et donc tout ce que les langages modernes ont! Parmi les fonctionnalit�s les plus essentielles, on peut citer :

\begin{itemize}
       \item acc�s facile et �naturel� aux structures de contr�le habituelles : boucles (\texttt{repeat}, \texttt{while}, \texttt{for}), tests simples, tests compos�s avec des op�rateurs logiques sur les conditions;
       \item fonctions dont les arguments sont �valu�s par un \idx{pr�processeur};
       \item nombres, qui sont d'un seul type, les d�cimaux � virgule flottante. Ceux-ci sont assortis des op�rations arithm�tiques et d'une biblioth�que de fonctions math�matiques;
       \item variables typ�es (chaines de caract�res, bool�ens, tables);
       \item acc�s aux fonctions du syst�me (acc�s aux entr�es/sorties, aux fonctions de date, d'heure);
       \item etc.
\end{itemize}

L'acc�s � \texttt{lua} peut donc grandement faciliter la vie d'un programmeur pour �crire des algorithmes qui autrement, seraient difficiles � coder en \TeX. Cela ne doit tout de m�me pas faire oublier que certains algorithmes \emph{doivent} �tre cod�s en \TeX, car c'est le langage qui a le dernier mot en mati�re de composition.

Mais il y a bien plus important. Le plus �tonnant est que \texttt{lua} permet aussi l'acc�s aux m�canismes les plus intimes de \TeX{}. Les auteurs ont r�ussi le tour de force d'impl�menter \texttt{lua} � un niveau tellement bas qu'il est possible d'agir sur le programme \texttt{tex} lui-m�me et d'acc�der � des endroits auparavant inaccessibles et non modifiables (on dit qu'ils sont cod�s �en dur�). Cet acc�s ouvre des possibilit�s inou�es, car lors de la compilation et par l'interm�diaire de \texttt{lua}, il devient possible de modifier ou contr�ler des comportements tr�s fins de \TeX, le rendant extr�mement configurable, bien plus qu'il ne l'�tait. Il devient possible, par exemple, d'effectuer ces actions qui �taient impossibles avant :

\begin{itemize}
       \item relever les positions de toutes les espaces inter-mots d'un paragraphe afin de v�rifier que certaines d'entre elles, au-del� d'un certain nombre, ne soient pas adjacentes et align�es verticalement, cr�ant ainsi ce que l'on appelle en typographie des �rivi�res� ;
       \item lors de l'affichage, remplacer chaque occurrence d'un groupe de caract�res par un autre, par exemple, tous les �onsieur� par �adame�;
       \item etc.
\end{itemize}\idx*[|)]{moteur!luatex}

\section{Et le bon dans tout �a?}
Bien �videmment, de \TeX{}, \LaTeX3 et lua\TeX, aucun n'est le bon, la brute ou le truand ! Chacun a ses propres caract�ristiques et chacun cohabite avec les deux autres sans qu'aucun ne soit en comp�tition avec un autre. Au contraire, il faut se r�jouir puisque le monde de \TeX{}, d�j� d'une extr�me complexit�, mais presque fig� depuis 1982 est en pleine effervescence et promet maintenant de fa�on certaine que des choses impossibles auparavant ne le seront plus. L'avenir s'ouvre riche en perspectives et sans r�ver, ne peut-on pas imaginer, d'ici quelques ann�es, un \idx{format} bas� sur le moteur lua\TeX{}\idx*{moteur!luatex} contenant les macros pr�compil�es de \LaTeX3, le tout formant une unit� r�unissant les trois protagonistes qui sera d'une puissance et d'une souplesse jusqu'alors inconnues ? Peut-on d�j� mesurer l'immense bond en avant que constituera cette symbiose ? Et que feront les packages de cette nouvelle �re s'ils savent exploiter les trois langages, quels miracles seront-ils capables de r�aliser ?

\chapter{Avant de commencer}
\section{La programmation \TeX{} oui, mais pour qui ?}
Finalement, � qui s'adresse ce livre ?
\grandsaut

Tout d'abord aux utilisateurs de plain-\TeX, \LaTeX{} ou d'un autre \idx{format} qui souhaitent acqu�rir un peu d'autonomie dans la programmation en \TeX. Car un jour ou l'autre c'est in�vitable, on en a besoin, ne serait-ce que parce que les packages disponibles n'ont pas ne couvrent pas tous les cas ou parce qu'on ignore qu'un package r�pondant � un besoin pr�cis existe. \Qu 'y a-t-il de plus frustrant que de renoncer en se sachant incapable d'�crire le moindre code non lin�aire, surtout lorsqu'on en a un urgent besoin ? \Qu elle satisfaction intellectuelle retire-t-on lorsqu'au moindre probl�me urgent et incontournable, on est contraint de poser une question de programmation \TeX{} sur un forum sp�cialis� ? Est-ce vraiment valorisant d'attendre une r�ponse, � copier-coller � le code donn� par un connaisseur sans en comprendre le fonctionnement et se dire qu'au prochain probl�me, il faudra poser une question � nouveau ?

Ce livre s'adresse aussi aux curieux, � ceux d�sireux d'apprendre, ceux qui souhaitent soulever un coin du voile. En effet, \TeX{} est r�put� comme �tant un langage r�serv� � quelques �initi�s�, voire carr�ment inaccessible si l'on n'est pas �\TeX-compatible�. La lecture de ce livre dissipera un peu l'aura quasi mystique qui l'enveloppe --~c'est en tout cas un des buts recherch�s~--, assouvissant les l�gitimes interrogations que se posent les �non-initi�s� � son sujet.

Il s'agit aussi de faire red�couvrir qu'il existe d'autres voies en programmation et celle que prend \TeX{} est des plus originales. Car finalement, tous les �poids lourds� des langages modernes ne tendent-ils pas � se ressembler tous ? Ne proposent-ils pas un peu tous les m�mes fonctionnalit�s, au moins jusqu'� un certain niveau ? Il est assez excitant de d�couvrir un langage de macros tellement ceux-ci sont rares\footnote{Le langage � \texttt{M4} � est �galement un langage de macros.}. L'apprentissage d'un tel langage est excitant d'abord parce que cela �tend la culture informatique, mais surtout parce cela ouvre de nouvelles voies en programmation en suscitant des m�thodes de programmation nouvelles. Il est d'ailleurs reconnu que les langages de macros sont puissants, m�me s'ils proc�dent � des remplacements \emph{aveugles} de macros par leur \idx{texte de remplacement}. Ce manque d'�valuation se paie par des erreurs parfois difficiles � corriger, car surgissant � des moments ou � des endroits tr�s �loign�s de l'origine du probl�me.
\grandsaut

Bien s�r, nulle part nous n'apprendrons � programmer des macros aussi complexes que celles de \LaTeX3, nous resterons beaucoup plus modestes. Le but de ce livre est de donner les cl�s pour comprendre \emph{comment} il faut s'y prendre. La compr�hension de quelques concepts doit pousser, au fur et � mesure de la lecture, � coder soi-m�me et essayer de voler de ses propres ailes. Il est en effet primordial, quel que soit le niveau atteint, de toujours exp�rimenter par soi-m�me, car se contenter d'une lecture lin�aire ne peut suffire. Imaginerait-on qu'un joueur d�butant de bridge, jeu complexe s'il en est, deviendrait subitement un bon joueur apr�s avoir simplement lu d'un trait un ouvrage sur le sujet ? La r�ponse est �videmment n�gative, car tester, modifier, adapter, exp�rimenter, se � planter �, apprendre de ses erreurs, recommencer, recommencer encore fait partie de tout apprentissage. Cela est valable dans tous les domaines, et en programmation --~surtout en \TeX~-- peut-�tre encore davantage !
\section{Ce qu'il faut savoir}
Il ne serait pas raisonnable d'aborder le c�t� langage de \emph{programmation} de \TeX{} sans avoir jamais pratiqu� \TeX{}, \LaTeX{} ou un autre \idx{format} en tant que langage de \emph{composition}. Non, vraiment pas raisonnable. Cette pratique est indispensable, ne serait-ce que pour s'impr�gner de la syntaxe et se familiariser avec l'outil. Ce livre ne s'adresse donc pas au d�butant de la premi�re heure, sauf inconscient ou masochiste qui souhaiterait se d�gouter � tout jamais de \TeX{} !

Mais tout compte fait et nous allons le voir ci-dessous, les choses � savoir ne sont pas l�gion.

\subsection{\TeX{} et la composition}
Il faut avoir une petite id�e de la fa�on dont \TeX{} compose du texte. Le sch�ma mental le plus proche de la r�alit� est de se dire que \TeX{} fonctionne par placement de boites sur la page. La g�om�trie des boites de \TeX{} est assez facile � comprendre. Voici la lettre �g�, �crite en tr�s grand et dont on a trac� les contours de la \emph{boite englobante}\idx*{boite!englobante} qui traduit les dimensions avec lesquelles \TeX{} voit une boite :

\begin{centrage}
\dimenbox[75]{g}\global\setbox\testbox\hbox{\unhbox\testbox}
\end{centrage}

Comme on peut le voir, la boite englobante\idx*{boite!englobante} a trois dimensions\idx*{boite!dimension}\idx*{boite!g�om�trie}, tout comme n'importe quelle boite dans le monde de \TeX{}\idx*{boite!g�om�trie} :%
\begin{itemize}
       \item une largeur qui est ici de \the\wd\testbox;
       \item une hauteur, de \the\ht\testbox
       \item une profondeur �gale � \the\dp\testbox
\end{itemize}

\TeX{} exprime naturellement les dimensions en \emph{points}\idx*{pt (unit�)}\idx*{unit�!pt} (mais nous le verrons, il y a bien d'autres unit�s possibles), et un centim�tre\idx*{unit�!cm}\idx*{cm (unit�)} contient exactement \texttt{\the\dimexpr1cm\relax}.

La hauteur et la profondeur s'�tendent verticalement de part et d'autre de la \emph{\idx{ligne de base}}. C'est une ligne horizontale th�orique autour de laquelle s'organise la g�om�trie d'une boite. Pour les boites contenant les caract�res, sa position pratique co�ncide avec le bas des caract�res sans jambage comme �a,�, �b�, �c�, etc.\medbreak

{%
\noindent\setbox0\hbox{\Large Programmer en \TeX{} est \emph{facile}.}%
\hfill
\rlap{\kern-1cm\vrule height0.2pt depth0.2pt width\dimexpr\wd0+2cm}%
\box0
\hfill\null
}%
\medbreak

Chaque boite a un point particulier, appel� \emph{\idx{point de r�f�rence}} situ� sur la fronti�re gauche de la \idx*{boite!englobante}boite englobante. Ce point de r�f�rence est, dans la boite contenant �g�, repr�sent� par un point �\tikz\draw[fill,black](0.35pt,0pt)circle(1pt);�. Les boites sont donc correctement plac�es verticalement parce que leur point de r�f�rence vient sur la \idx{ligne de base} de la ligne courante, et sont positionn�es les unes � la suite des autres parce que le \idx{point de r�f�rence} de la boite suivante est situ� sur la fronti�re droite de la boite pr�c�dente.

\TeX{} proc�de par �-coups, composant tour � tour des paragraphes\idx*[|(]{paragraphe!composition}. La m�canique fonctionne de cette mani�re : lorsque la commande \idx\par est rencontr�e, le paragraphe qui vient d'�tre lu et qui est jusqu'alors stock� en m�moire est � compos� �. C'est le moment o� \TeX{} appr�hende le paragraphe dans sa totalit� pour d�cider o� se feront les coupures de ligne. Chaque ligne de texte est ainsi constitu�e

\begin{itemize}
       \item de boites contenant les caract�res\footnote{Pour �tre clair, \TeX{} ne connait � aucun moment le dessin de chaque caract�re. Il ne connait que les dimensions de la boite qui le contient, qui est la boite englobante.}. Dans un mot, chaque boite est adjacente � la pr�c�dente;
       \item d'espaces qui peuvent, dans une certaine mesure, s'�tirer ou se comprimer de telle sorte que la largeur de la ligne soit exactement celle de la largeur du paragraphe. La derni�re ligne du paragraphe, moins large que ne l'est le paragraphe, a des espaces qui ont leur largeur naturelle.
\end{itemize}

Pendant tout le paragraphe, \TeX{} positionne cette \emph{liste} d'�l�ments � la suite les uns des autres de fa�on horizontale pour former chaque ligne : on dit qu'il fonctionne en �mode horizontal\idx*{mode!horizontal}�. Ce mode est d'ailleurs celui dans lequel il se trouve pour la plupart du temps lorsqu'il compose du texte.

La composition proprement dite du paragraphe enferme chaque ligne dans une boite et les boites contenant les lignes sont positionn�es \emph{verticalement} les unes sous les autres, chacune �tant s�par�e de sa voisine par un � \idx{ressort d'interligne} � (page~\pageref{ressort.interligne}).

\begingroup
\clubpenalty=0 % pas de p�nalit� suppl�mentaire apr�s la premi�re ligne
\interlinepenalty=0 % pas de p�nalit� inter-ligne
\widowpenalty=0 % pas de p�nalit� suppl�mentaire avant la derni�re ligne
\leftline{}
\let\formatline\frbox
\frboxrule=0.3pt
\frboxsep=-\frboxrule% encadrer vers "l'int�rieur"
\numlines
On peut observer ce \idx{ressort d'interligne} dans ce paragraphe o� la boite englobante\idx*{boite!englobante} de chaque ligne est trac�e. On peut constater que la boite englobante d'une ligne ne touche pas celle de ses voisines : l'espace vertical qui les s�pare est l'espace interligne. Si cet espace �tait nul, les lignes seraient beaucoup trop serr�es et cela rendrait la lecture tr�s p�nible.
\endnumlines
\endgroup

Apr�s avoir form� le paragraphe (et donc apr�s avoir ex�cut� la commande \idx\par), le mode\idx*{mode!vertical} vertical est en vigueur, puisque \TeX{} vient de placer les lignes du paragraphe pr�c�dent verticalement : il est donc pr�t � positionner d'autres �l�ments verticalement les uns sous les autres. Bien �videmment, si un nouveau paragraphe commence juste apr�s, \TeX{} repasse en mode horizontal\idx*{mode!horizontal} d�s le premier caract�re rencontr�.

Au fur et � mesure que les lignes et autres objets remplissent verticalement la page, il arrive un moment o� un certain seuil de remplissage est atteint et \TeX{} d�cide o� se situe la coupure de page.  La page destin�e � �tre compos�e est � ce moment enferm�e dans une ultime boite. Cette boite signe la fin de l'imbrication des boites en poup�es gigognes et est envoy�e vers le fichier de sortie.\idx*[|)]{paragraphe!composition}%

\subsection{\Qu elques commandes utiles}
\subsubsection{\texttt{\textbackslash par} et les changements de mode}
La plus courante de toutes les primitives est sans doute \idx\par puisque sans elle, il n'y aurait pas de \idx{paragraphe} et donc pas de typographie. Ajoutons � ce qui a �t� dit ci-dessus la r�gle suivante :

\label{par.consecutifs}\begin{regle}
Lorsque \TeX{} est en mode vertical\idx*{mode!vertical}, la commande \idx[!mode vertical]\par\idx*{mode!vertical} est sans effet.

Par cons�quent, si l'on se trouve en mode horizontal\idx*{mode!horizontal} et si plusieurs commandes \idx[!cons�cutifs]\par se suivent, seule la premi�re est utilis�e pour composer le paragraphe en cours et les autres sont ignor�es.
\end{regle}

On peut quitter le mode vertical\idx*{mode!vertical} sans afficher aucun caract�re avec la macro de plain-\TeX{} \idx\leavevmode.

D'autres primitives commandent � \TeX{} le passage en mode horizontal\idx*{mode!horizontal}, mais font aussi autre chose :
\begin{itemize}
       \item \idx\indent ins�re au d�but de la liste horizontale une espace de valeur \idx\parindent, qui est la primitive contenant la dimension du retrait de la premi�re ligne d'un paragraphe (plain-\TeX{} initialise cette dimension � \texttt{20pt} en proc�dant � l'assignation �\verb*|\parindent=20pt |�);
       \item \idx\noindent demande � ce que le prochain paragraphe\idx*{paragraphe!indentation} ne soit pas indent�, c'est-�-dire que sa premi�re ligne ne commence pas en retrait.
\end{itemize}

\subsubsection{Espaces s�cables et ins�cables}
La primitive \idx\kern, suivie d'une dimension, ins�re dans la liste courante une espace ins�cable\idx*{espace!ins�cable} de la dimension voulue. Cette espace est ins�cable, car aucune coupure (de page ou de ligne) ne pourra se faire sur cette espace. Il est important de noter que \idx\kern ob�it au mode en cours; l'espace est horizontale si \TeX{} est en mode horizontal\idx*{mode!horizontal} et sera verticale sinon. Voici ce qu'il se passe si l'on �crit \verb|A\kern 5mm B| :

\begin{centrage}
       A\kern 5mm B
\end{centrage}

\noindent L'espace de \texttt{5mm} se trouve entre le bord droit de la boite englobante\idx*{boite!englobante} de � A � et le bord gauche de la boite englobante de � B �.

Pour ins�rer une espace verticale suppl�mentaire de \numprint[mm]5
entre deux lignes, il suffit de passer en mode vertical\idx*{mode!vertical} avec \idx\par pour que \idx\kern agisse dans ce mode. Ainsi, \verb|A\par\kern 5mm B| se traduit par :

\begin{centrage}
       A\par\kern 5mm B
\end{centrage}
\grandsaut

L'espace entre le bas de la lettre �A� et le haut de la lettre �B� est l�g�rement sup�rieure � \numprint[mm]5 car le \idx{ressort d'interligne} s'ajoute � l'espace sp�cifi�e par \idx\kern.\grandsaut

Si l'on veut ins�rer des espaces \emph{s�cables}\idx*{espace!s�cable}, c'est-�-dire susceptibles d'�tre \emph{remplac�es}\footnote{Il faut bien lire � remplac�es �, car une espace s�cable est supprim�e si elle se trouve � un endroit de coupure. Les espaces s�cables les plus courantes sont les espaces tap�s dans le code pour s�parer les mots.} par une coupure de ligne ou de page, il faut utiliser soit \idx\hskip, soit \idx\vskip. La premi�re lettre d�signant le mode dans lequel on veut que cette espace soit ins�r�e et commandant le passage dans ce mode. Ces deux primitives doivent �tre suivies d'une dimension de ressort (voir page~\pageref{dimension.ressort}). Plain-\TeX{} met � disposition deux macros \idx\quad et \idx\qquad ins�rant respectivement une espace horizontale s�cable\idx*{espace!s�cable} de \verb|1em| et de \verb|2em|. L'unit� \verb|em|\idx*{unit�!em} d�pend du contexte : c'est la dimension horizontale de la boite englobante\idx*{boite!englobante} de lettre �\verb|m|�, compos�e dans la fonte en cours.

La macro \idx\smallskip ins�re verticalement � l'aide de \idx\vskip l'espace �lastique stock�e dans le registre \idx\smallskipamount et qui vaut dans plain-\TeX{} �\texttt{3pt plus 1pt minus 1pt}�. Les variantes \idx\medskip et \idx\bigskip ins�rent des espaces verticales �gales respectivement � 2 fois et 4 fois \idx\smallskipamount.

Les macros \idx\smallbreak, \idx\medbreak et \idx\bigbreak se comportent comme leurs s\oe urs en �skip� mais elles v�rifient tout d'abord que la pr�c�dente espace verticale qui les pr�c�de est inf�rieure � celle qui doit �tre ins�r�e. Dans ce cas seulement, ces macros favorisent une coupure de page (par l'insertion d'une \idx{p�nalit�} de $-50$, $-100$ ou $-200$), suppriment la pr�c�dente espace verticale et ins�rent l'espace par l'interm�diaire de \idx\smallskip, \idx\medskip et \idx\bigskip.

\subsubsection{\texttt{\textbackslash relax}}
La primitive \idx\relax est la plus simple � comprendre puisqu'elle ne provoque aucune action. Elle est cependant utile notamment pour marquer clairement la fin d'un nombre ou d'une dimension et �vite que \TeX{} n'aille chercher des choses au-del�. Elle fait aussi partie, mais de fa�on optionnelle, de la syntaxe des primitives \idx\numexpr et \idx\dimexpr de \idx\eTeX{} (voir pages~\pageref{numexpr} et \pageref{dimexpr}).

\subsubsection{Commandes de fontes}
Les commandes suivantes, programm�es dans le format plain-\TeX, agissent comme des � bascules � et s�lectionnent une forme de fonte :

\begin{centrage}
\small
\begin{tabular}{ccc}\hline
       Commande \TeX & �quivalent \LaTeX & Exemple\\\hline
       \idx\bf & \idx\bfseries & \bf fonte en gras\\
       \idx\it & \idx\itshape & \it fonte italique\\
       \idx\tt & \idx\ttfamily & \tt fonte � chasse fixe\\
       \idx\sc & \idx\scshape & \sc fonte petite majuscule\\\hline
\end{tabular}
\end{centrage}

Par ailleurs, en \idx*{mode!math�matique}mode math�matique, la primitive \idx\scriptstyle fonctionne �galement comme une bascule au niveau de la taille de la fonte qui est affich�e dans la taille des exposants. De la m�me fa�on, \idx\scriptscriptstyle s�lectionne une taille encore plus petite, celle des � exposants d'exposants � :

\showcode/3 tailles : $% entre en mode math�matique (espaces ignor�s)
1^{2^3}% 2 est en taille "\scriptstyle" et 3 en taille "\scriptscriptstyle"
$% fin du mode math�\idx*{mode!math�matique}�

normal $1$, petit $\scriptstyle 2$, tr�s petit $\scriptscriptstyle 3$.�\idx*\scriptstyle\idx*\scriptscriptstyle�/

\subsubsection{Les boites}
Venons-en maintenant aux \idx{boite}s, non pas celles que \TeX{} construit automatiquement lors de la composition, mais de celles qui sont mises � disposition de l'utilisateur pour qu'il puisse enfermer dedans un contenu arbitraire.

\TeX{} met � disposition trois primitives permettant d'enfermer du mat�riel dans des boites :
\begin{itemize}
       \item \idx\hbox\verb|{<contenu>}| enferme le \verb|<contenu>| dans une boite horizontale, �tant entendu que ce contenu ne peut �tre compos� qu'en mode horizontal\idx*{mode!horizontal} et doit donc �tre exempt de commande sp�cifiquement verticale (\idx\par ou \idx\vskip y sont interdits puisque passant en mode vertical\idx*{mode!vertical});
       \item \idx\vbox\verb|{<contenu>}| construit une boite verticale dans laquelle chaque �l�ment du \verb|<contenu>| est empil� sous l'�l�ment pr�c�dent et o� r�gne le mode vertical \emph{interne}\idx*{mode!vertical interne}. Le \idx{point de r�f�rence} de la boite ainsi obtenue co�ncide avec celui du dernier �l�ment (le plus bas donc). Autrement dit, la \idx{ligne de base} de la \idx\vbox co�ncidera donc avec la \idx{ligne de base} de l'�l�ment le plus bas. Par cons�quent, s'il y a $n$ �l�ments dans la \idx\vbox, les $n-1$ premiers seront plac�s au-dessus de la \idx{ligne de base} de la ligne courante comme le montre la figure ci-dessous ;
       \item \idx\vtop\verb|{<contenu>}| proc�de comme \verb|\vbox| sauf que le \idx{point de r�f�rence} de la \idx\vtop co�ncide avec celui du \emph{premier} �l�ment (le plus haut). Les $n-1$ derniers �l�ments sont donc au-dessous de la \idx{ligne de base} de la ligne courante.
\end{itemize}

Voici deux constructions, l'une avec \idx\vbox et l'autre avec \idx\vtop o� les fronti�res des boites ont �t� rendues visibles et o� les points de r�f�rences de chaque boite ont �t� symbolis�s par un point �\tikz\draw[fill,black](0.35pt,0pt)circle(1pt);�. Pour les besoins de l'exemple, chaque boite contient trois �l�ments.

\begin{centrage}\footnotesize
       Voici une \idx\vbox : \drawbox{\vbox{\hbox{\drawbox{La premi�re ligne}}\hbox{\drawbox{La deuxi�me}}\hbox{\drawbox{Et la troisi�me}}}} puis une \idx\vtop : \drawbox{\vtop{\hbox{\drawbox{La premi�re ligne}}\hbox{\drawbox{La deuxi�me}}\hbox{\drawbox{Et la troisi�me}}}}
\end{centrage}

Le mode en cours dans ces boites est le mode \emph{interne}\idx*{mode!interne}. Il s'agit du mode horizontal interne\idx*{mode!horizontal interne} pour \idx\hbox et du mode vertical interne\idx*{mode!vertical interne} pour \idx\vbox et \idx\vtop.\grandsaut

Une boite construite avec l'une des trois primitives \idx\hbox, \idx\vbox ou \idx\vtop est \emph{ins�cable}. Il n'existe donc aucun m�canisme qui permet de couper une boite ainsi construite\label{boite.insecable}. Il est donc n�cessaire d'�tre prudent sur les d�bordements\idx*{d�passement (marge)} qui peuvent en r�sulter :

\begin{itemize}
       \item en mode horizontal\idx*{mode!horizontal}, ces d�bordements ont lieu dans la marge de droite ;
       \item en mode vertical interne\idx*{mode!vertical interne}, ils ont lieu dans la marge inf�rieure.
\end{itemize}

{\hfuzz=\maxdimen Pour illustrer ce propos, voici ce qui arrive si on tente d'enfermer ces \hbox{\bfseries mots en gras} dans une \idx\hbox. On peut constater que la coupure de ligne n'a pu se faire et que la boite d�passe dans la marge de droite. Cela signifie que malgr� tous ses efforts pour comprimer ou �tirer les espaces, couper des mots, mixer ces possibilit�s pour examiner plusieurs solutions, \TeX{} n'a pu composer le paragraphe\idx*{paragraphe!composition} pour faire en sorte que cette \idx\hbox se trouve entre les fronti�res du texte. Dans le cas pr�sent, cet �chec est d� � la trop grande largeur de la boite et au fait qu'elle se situe � un endroit proche du d�but du paragraphe, o� la latitude d'organiser diff�remment ce qui pr�c�de est assez r�duite. \TeX{} avertit l'utilisateur qu'une anomalie dans la composition du paragraphe a eu lieu par un message dans le \idx[!log]{fichier} \verb|log|: c'est le fichier produit par \TeX{} lors de la compilation d'un code source. Ce fichier contient des informations de compilation et a le m�me nom que le fichier compil� mais porte l'extension �\texttt{.log}�. Concernant ce d�bordement, on lit dans ce ficher �\texttt{Overful \string\hbox{} (9.74199pt too wide) in paragraph}�, ce qui signifie qu'une boite horizontale (la boite horizontale dont il est question est ici la ligne en cours) est trop large de 9.74199pt par rapport � la largeur du texte.\par}

\section{Demandez le programme}
Le chemin choisi pour aborder la programmation en \TeX{} va sembler, c'est s�r, long et ingrat. Il ob�it cependant � une logique qui apparaitra plus tard au lecteur. Les parties I et II ne sont pas consacr�es � la programmation, mais aux nombreuses sp�cificit�s du langage \TeX{} sans lesquelles il est impossible de construire le moindre programme. C'est par souci de clart� et pour b�tir des bases solides que ces sp�cificit�s sont abord�es \emph{avant} d'entrer dans le vif du sujet. Renoncer � ces explications pr�liminaires aurait conduit � d'innombrables digressions, chacune apparaissant � une nouvelle sp�cificit�, et troublant plus le discours qu'autre chose. Ainsi, la partie I montrera comment et selon quelles r�gles \TeX{} lit le code source pour le transformer en mati�re exploitable que sont les \idx{token}s. La partie suivante exposera les nombreuses sp�cificit�s des macros de \TeX{} et comment les construire afin de maitriser cet outil fondamental de programmation.

Ce n'est qu'ensuite, � la partie III, que nous nous lancerons dans le grand bain et commencerons � b�tir des algorithmes. Nous verrons, � l'aide d'algorithmes relativement peu complexes, quelles m�thodes de programmation nous pouvons mettre en \oe uvre en \TeX{} et quels �cueils nous devons �viter. La partie IV s'inscrit dans la continuit� de la partie III, mais les m�thodes employ�es diff�rent en ce sens que la granularit� de la lecture du code effectu�e par les macros sera plus fine.

Enfin, la derni�re partie sera consacr�e � des algorithmes un peu plus complexes mettant � profit les notions vues jusqu'alors.
%|                                                                            |
%|                              Fin introduction                              |
%|____________________________________________________________________________|

% ____________________________________________________________________________
%|                                                                            |
%|                                  Partie 1                                  |
%|                                                                            |
\defpartcomment{\lettrine[lines=3,slope=4pt,nindent=0pt]{\libertineInitialGlyph{A}}{\kern -5pt vant} d'entrer dans le vif du sujet, il nous faut comprendre un des m�canismes fondamentaux de \TeX{}, le premier dont il est question lorsque \TeX{} fonctionne : comment lit-il le code qui est tap� par l'utilisateur ? Et qu'est-ce r�ellement du code tap� par l'utilisateur ? Les r�ponses � ces questions non triviales permettent non seulement de lever une petite partie du myst�re qui entoure le fonctionnement de \TeX{} mais surtout posent des bases essentielles.}

\part{\TeX{} et le code source}
\chapter{Comment \TeX{} lit-il le code source ?}
Pour bien r�pondre � cette question, il faut d'abord d�finir ce qu'est du �code tap� par l'utilisateur�. Ce code, la plupart du temps stock� dans un fichier, est consid�r� et lu par \TeX{} \idx{octet}\footnote{Un octet est une suite de 8 bits. Cette suite peut �tre comprise comme un nombre constitu� de 8 chiffres en base 2. Si l'on convertit ce nombre en base 10 alors, ce nombre peut varier de $2^0-1$ � $2^8-1$, c'est-�-dire de 0 � 255 ou \Hex{00} � \Hex{FF} en hexad�cimal.} par \idx{octet}; c'est d'ailleurs ainsi qu'il est stock� sur les disques durs de nos ordinateurs. Ainsi la r�solution de lecture de \TeX{} est toujours la m�me, le code tap� par l'utilisateur est vu par \TeX{} comme une suite d'\idx{octet}s.
\grandsaut

Un �\idx{�diteur}� est un logiciel totalement ind�pendant de \TeX{} dont les fonctions les plus basiques sont de permettre la saisie de \emph{texte} et la sauvegarde de ce texte dans un fichier. Il existe des quantit�s d'�diteurs\footnote{Citons pour les plus reconnus vim et emacs du c�t� de UNIX/GNU-linux et notepad++ du c�t� de Windows.} diff�rents, avec des fonctions plus ou moins nombreuses, parfois pl�thoriques, certains �tant m�me sp�cialis�s dans la saisie de code \TeX\footnote{L� aussi, il y a du monde : auc\TeX{} qui est une extension d'emacs pour le sp�cialiser pour \TeX/\LaTeX, \TeX macs, kile, \TeX maker, \TeX works, etc.}. Lorsqu'on demande � l'�diteur d'enregistrer dans un fichier le texte que l'on a tap�, l'�diteur a la charge de \emph{convertir} les caract�res tap�s par l'utilisateur en une suite d'\idx{octet}s qui seront enregistr�s sur le disque dur sous forme d'un fichier texte.

Pour comprendre comment cette conversion est faite et quelle est la signification de ces \idx{octet}s, il faut savoir � quel �\idx{encodage}� ob�it l'�diteur lors de cette conversion. Un \idx{encodage} est une convention qui lie de fa�on biunivoque un caract�re � un (parfois plusieurs) \idx{octet}. Il est important de comprendre que c'est l'\emph{utilisateur}, en param�trant son �diteur, qui d�cide quel \idx{encodage} il d�sire utiliser, m�me si �videmment, un choix par d�faut est toujours s�lectionn� si l'on n'a pas fait la d�marche de modifier le param�tre ad�quat.
\grandsaut

L'\idx{encodage} ASCII\idx*{encodage!ASCII}\footnote{ASCII est l'acronyme pour �American Standard Code for Information Interchange�.} est commun � l'immense majorit� des autres \idx{encodage}s ce qui fait que l'ASCII joue le r�le de plus petit d�nominateur commun. Cette convention ASCII ne s'occupe que des \idx{octet}s compris entre 0 et 127 (ou \Hex{00} et \Hex{7F} en hexad�cimal). \TeX{} reconnait nativement l'ASCII dont on voit dans la table ci-dessous la correspondance entre \idx{octet}s et caract�res. Pour toutes les impl�mentations de \TeX{}, la relation entre \idx{octet} et caract�re affichable qui figure dans cette table est valide :

\def\carnonaff{\itshape}
\begin{centrage}
       \noindent
       \footnotesize
       \def\?#1{\ttfamily\bfseries x#1}%
       \newcount\charcnt \charcnt=-17
       \def\!{\global\advance\charcnt1 }%
       \def\:{\char\charcnt}%
       \let\^\carnonaff% marque un caract�re non affichable
       \newcolumntype G{m{\dimexpr(\linewidth-18\arrayrulewidth)/17\relax}}%
       \begin{tabular}{|@{}>{\columncolor{gray!40}[0pt][0pt]\hfill\ttfamily\bfseries}G<{x\hfill\null}@{}|*{16}{@{}>{\!\hfill\vrule height3.3ex depth.8ex width0pt }G<{\hfill\unless\ifnum\charcnt<0 \vtop{\kern1.5pt\normalfont\tiny\llap{\number\charcnt\kern.5pt}\kern1pt}\fi\null}@{}|}}
       \hline
               \rowcolor{gray!40}[0pt][0pt]\multicolumn1{|@{}G@{}|}{\cellcolor{white}}
               &\?0 &\?1 &\?2 &\?3 &\?4 &\?5 &\?6 &\?7 &\?8 &\?9 & \?A& \?B&\?C &\?D &\?E & \?F\\\hline
               0 & \^NUL&\^SOH &\^STX &\^ETX &\^EOT &\^ENQ &\^ACK &\^BEL & \^BS &\^HT  & \^LF & \^VT & \^FF & \^CR & \^SO & \^SI \\\hline
               1 & \^DLE&\^DCI & \^DC2& \^DC3& \^DC4& \^NAK& \^SYN& \^ETB& \^CAN& \^EM & \^SUB& \^ESC& \^FS & \^GS & \^RS & \^US \\\hline
               2 & SP & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: \\\hline
               3 & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: \\\hline
               4 & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: \\\hline
               5 & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: \\\hline
               6 & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: \\\hline
               7 & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \: & \^DEL\\\hline
       \end{tabular}
\end{centrage}

Dans ce tableau, les cases gris�es portent les deux chiffres hexad�cimaux qui formeront le num�ro de l'octet. Le nombre en bas � droite de chaque case est le num�ro de l'octet en base 10. Par exemple, le caract�re �A� correspond � l'octet \Hex{41} dont la valeur d�cimale est 65.

On remarque que quelques octets codent des caract�res non affichables. Ceux-ci sont affich�s en italique\footnote{Les acronymes dans les cases des caract�res non imprimables correspondent � des noms qui ont �t� donn�s � ces octets lors de la cr�ation de cet \idx{encodage}. Pour la plupart, ces octets �taient ins�r�s dans des flux de donn�es lors de t�l�transmission et avaient une signification li�e � la communication entre deux ordinateurs distants. Par exemple, l'octet {\carnonaff EOT\/} signifie � End Of Transmission� c'est-�-dire � Fin de Transmission�, {\carnonaff NAK\/} signifie �Negative Acknowledge� pour �Accus� de r�ception n�gatif�. Ces fonctions sont �videmment sans objet pour un traitement de texte comme \TeX{}. Ces caract�res n'ont donc pas de signification particuli�re pour \TeX{} � l 'exception de quelques caract�res non imprimables dont la fonction est rest�e la m�me : {\carnonaff HT\/} pour �tabulation horizontale� (le caract�re ins�r� avec la touche �Tab� \bioLegacyKeyGlyph{T_a_b}), {\carnonaff LF\/} pour �saut de ligne� et {\carnonaff CR\/} pour �retour charriot�.} dans la table. Ils ont des codes hexad�cimaux compris entre \Hex{00} et \Hex{1F} inclus auxquels il faut rajouter le caract�re de code \Hex{7F}.
\grandsaut

Pendant la compilation, � chaque fois que \TeX{} lit un \idx{octet} --~pour l'instant, disons par abus de langage un �caract�re�~--, il lui affecte une bonne fois pour toutes un �code de cat�gorie� ou �\idx{catcode}� et de fait, chaque caract�re lu dans le fichier a donc \emph{deux} codes pour \TeX:
\begin{itemize}
       \item le \idx{code de caract�re}, c'est-�-dire la valeur de l'\idx{octet} lu dans le code source et qui est li� � la table ASCII vue pr�c�demment;
       \item le code de cat�gorie\idx*{catcode} qui est affect� par \TeX{} lors de sa lecture. Ces codes de cat�gorie sont des entiers qui vont de 0 � 15 et qui donnent au caract�re des propri�t�s qui sont celles de la cat�gorie � laquelle il appartient.
\end{itemize}

Voici les diff�rentes \idx{cat�gories} ainsi que pour chacune, les caract�res qui les peuplent par d�faut :

\begin{centrage}
       \label{catcode.table}\small
       \let\^\carnonaff% marque un caract�re non affichable
       \LTpre\parskip \LTpost\parskip\idx*{catcode!table des catcodes}
       \begin{longtable}{>{\leftskip0ptplus1fill \rightskip\leftskip}m{1.5cm}m{4.5cm}m{3cm}}\hline

               N�{} de\par cat�gorie & Signification & Caract�res\par concern�s\\\hline\endhead
               0 & \idx{caract�re d'�chappement} & \texttt\textbackslash\\
               1 & d�but de groupe & \ttfamily\{\\
               2 & fin de groupe & \ttfamily\}\\
               3 & d�limiteur de mode math�matique\idx*{mode!math�matique} & \ttfamily\$\\
               4 & tabulation d'alignement & \ttfamily\&\\
               5 & retour charriot & \^LF\\
               6 & caract�re de param�tre & \ttfamily\#\\
               7 & exposant & \ttfamily\string^\\
               8 & indice & \ttfamily\string_\\
               9 & caract�re ignor� & \^NUL\\
               10 & \idx{espace} & SP et \^HT\\
               11 & lettres & \texttt{A...Z}\quad et\quad\texttt{a...z}\\
               12 & autres caract�res &\\
               &\qquad-- chiffres & \ttfamily0 1 2 3 4 5 6 7 8 9\\
               &\qquad-- signes de ponctuation & \ttfamily\string: . \string; , \string? \string! \string' \string"\\
               &\qquad-- signes math�matiques & \ttfamily + - * / = < >\\
               &\qquad-- autres signes &\ttfamily [ ] ( ) | @ \string`\\
               13 & caract�re actif & \ttfamily\string~\\
               14 & caract�re de commentaire & \ttfamily\%\\
               15 & caract�re invalide & \^DEL\\
               \hline
       \end{longtable}
\end{centrage}

Dans toute la suite du livre, sauf indication contraire, lorsqu'il est dit par abus de langage � lettre � ou bien � accolade ouvrante �, il est sous-entendu � caract�re de catcode 11\idx*{catcode!11 (lettre)} � ou � caract�re de catcode 1\idx*{catcode!1 (accolade)} �.

Comme on le voit, certaines cat�gories sont tr�s peupl�es (celles dont le num�ro est 11 ou 12) alors que d'autres ne contiennent qu'un seul �l�ment. Ceci s'explique par le fait que seules les cat�gories de num�ro 10, 11 et 12 comportent des caract�res \emph{affichables} pour \TeX. Les autres ne comportent que des caract�res qui commandent une action � \TeX{}, par exemple de passer en mode math�matique\idx*{mode!math�matique} pour le caract�re �\verb-$-�. Comme il n'y a pas de raison pour que plusieurs caract�res rev�tent cette propri�t�, il est logique de ne trouver qu'un seul caract�re dans la cat�gorie n�3. Le m�me raisonnement s'applique aux autres cat�gories ne comportant qu'un seul caract�re.

L'\idx{espace}, bien qu'affichable, se trouve dans une cat�gorie � part, car il ob�it � des r�gles diff�rentes que celles des autres caract�res affichables, notamment lors de la lecture du code source :

\label{espaces.consecutifs}\begin{regle}
Lorsque plusieurs espaces\idx*{espace!cons�cutifs} (ou plus g�n�ralement �caract�res de catcode 10�\idx*{espace!catcode 10})\idx*{catcode!10 (espace)} se suivent dans le code source, \TeX{} ne prend en compte que le premier d'entre eux et ignore les autres.

Si une ligne de code source commence par des espaces\idx*{espace!d�but de ligne}, ceux-ci sont ignor�s.

Plain-\TeX{} et \LaTeX{} assignent au caract�re de tabulation ({\carnonaff HT\/}) le catcode de 10 ce qui signifie que ce caract�re rev�t toutes les propri�t�s de l'espace.
\end{regle}

Pour fixer les id�es, supposons que \TeX{} ait � lire le code suivant :

\centrecodespc-\hbox{Et $x$ vaut  3,5.}-

\noindent Au fur et � mesure de sa lecture, il attribuera � chaque caract�re le code de cat�gorie en vigueur au moment o� il le lit et agira en cons�quence. Ce code de cat�gorie est attribu� de fa�on \emph{d�finitive} et ne peut pas �tre chang� ensuite ; il s'agit d'un m�canisme incontournable sur lequel il faut insister :

\label{catcode.inalterable}\begin{regle}
       D�s que \TeX{} lit un caract�re, il lui affecte de fa�on inalt�rable un \idx*{catcode}code de cat�gorie.
\end{regle}

Si lors de la lecture, les catcodes en vigueur sont ceux expos�s dans le tableau ci-dessus, voici sous chaque caract�re, le catcode qui lui sera affect� :

\def\falsespcverb{\leavevmode\vrule width0.2pt height .5ex depth 0pt
       \vrule width.75em height0.4pt depth 0pt
       \vrule width0.2pt height .5ex depth 0pt }
\begingroup
       \hfill
       \def~#1#2{%
               \hbox{%
                       \footnotesize
                       \vtop{\offinterlineskip\hbox to1em{\hss\ttfamily\strut#1\hss}\hbox to1em{\hss\tiny#2\hss}}%
               }%
       }
       ~\textbackslash0~h{11}~b{11}~o{11}~x{11}%
       ~\{1~E{11}~t{11}~\falsespcverb{10}~{\string$}{3}~x{11}%
       ~{\string$}{3}~\falsespcverb{10}~v{11}~a{11}%
       ~u{11}~t{11}~\falsespcverb{10}~3{12}~,{12}~5{12}~.{12}%
       ~\}2\hfill\null
\endgroup
\grandsaut

Un caract�re peut �tre tap� sous forme habituelle comme lorsqu'on tape un �\verb-a-�, mais on peut aussi utiliser �\verbidx[|(]{^^}�. En effet, si \TeX{} voit deux caract�res \emph{identiques} dont le code de cat�gorie est \number\catcode`\^{} (celui du caract�re de mise en exposant) et si ces deux caract�res sont suivis d'un caract�re dont le code --~appelons-le $c$~-- est compris entre 0 et 63 inclus, alors \TeX{} lit le tout comme �tant le caract�re dont le code est $c+64$. Par exemple, �\verb-^^:-� est le caract�re �^^:�. Il est rigoureusement �quivalent de taper �^^:� ou �\verb-^^:-� et ce, quel que soit l'endroit o� l'on se trouve dans le code source.

Sym�triquement, si le code de caract�re $c$ est compris entre 64 et 127 inclus, \TeX{} remplace le tout par le caract�re de code $c-64$. Et donc, il est �quivalent de taper �\verb-^^z-� ou �\string^^z�.

Ce qui est �crit dans les deux paragraphes pr�c�dents nous conduit donc � cette r�gle :

\begin{regle}
Lorsqu'on �crit �\verb-^^<car>-� dans le code source, tout se passe donc comme si \TeX{} voyait le caract�re se trouvant 4 lignes plus haut ou plus bas dans la table ASCII, selon que \verb-<car>- se trouve dans la partie basse ou haute de cette table.

Si les \emph{deux} caract�res qui suivent \verb-^^- forment un nombre hexad�cimal � deux chiffres minuscules pris parmi �\verb-0123456789abcdef-�, alors \TeX{} remplace ces 4 caract�res par le caract�re ayant le code hexad�cimal sp�cifi�. Avec cette m�thode, on peut donc facilement acc�der � n'importe quel caract�re. Le caract�re �z� peut aussi s'�crire �\verb-^^7a-�.
\end{regle}

Ainsi, le caract�re �t� �tant appari� via \verb-^^- avec un caract�re affichable (en l'occurrence �4� qui se trouve 4 lignes plus haut dans la table ASCII), �t� peut donc �tre tap� dans le code de 3 fa�ons �quivalentes : �\verb-t-� ou �\verb-^^4-� ou �\verb-^^74-�. Si l'on voulait rendre le code myst�rieux ou difficilement lisible, voici comment on pourrait �crire le mot �tex� :
\begin{itemize}
       \item \verb-^^4^^%^^8-
       \item \verb-^^74^^65^^78-
\end{itemize}

La seule petite ambig�it� qui subsiste dans cette belle m�canique est que l'on ne peut pas �crire un �t� sous la forme �\verb|^^4|� puis le faire suivre du caract�re �5�. En effet, cela formerait la suite de caract�res �\verb|^^45|� que \TeX{} interpr�terait comme �tant le caract�re de code hexad�cimal \Hex{45} qui est �E�\verbidx*[|)]{^^}.

Au-del� de l'originalit� de cette m�thode alternative pour �crire des caract�res dans le code source, ce qu'il faut en retenir est qu'elle peut �tre tr�s utile pour �crire des caract�res non affichables qui de toute fa�on, seraient difficilement accessibles au clavier. Ainsi, le caract�re de tabulation {\carnonaff HT} s'�crit �\verbidx[ (tabulation)]{^^I}�, le retour charriot {\carnonaff CR} �\verbidx[ (retour charriot)]{^^M}�, etc.
\grandsaut

On peut aussi \emph{afficher} un caract�re avec la primitive \idx\char suivie du num�ro du code de caract�re. Ainsi, \verb|\char97| affiche un �\char97� mais au contraire de la m�thode avec \verb|^^|, \verb|\char97| ne peut pas �tre utilis� dans le code source � la place d'une lettre. Autant �\verb|\p^^61r|� et �\verb|\par|� sont �quivalents, autant il n'est pas question d'�crire �\verb|\p\char65r|� � la place de \verb|\par| dans le code source, car ceci serait interpr�t� comme la commande \verb|\p|, suivie de \verb|\char65|, suivi de �r�.
\grandsaut

Enfin, il faut d�finir ce qu'est une �ligne de code source�. Pour \TeX{}, une ligne de code est constitu�e par les caract�res qui se trouvent avant la prochaine � marque de \idx{fin de ligne} �\label{marque.fin.ligne}. Cette marque est une convention qui d�pend du syst�me d'exploitation :

\begin{itemize}
       \item pour Windows, une marque de fin de ligne est constitu�e des octets \Hex{0D}\Hex{0A}, c'est-�-dire de {\carnonaff CR} suivi de {\carnonaff LF} (not� �CRLF�);
       \item pour GNU-linux, cette marque est l'octet \Hex{0A} (LF);
       \item enfin, pour MAC OS X, cette marque est l'octet \Hex{0D} (CR).
\end{itemize}

L'ex�cutable \texttt{pdftex} consid�re comme marque de fin de ligne les s�quences suivantes : LF, CR, CRLF et LFCR. Les \idx[!fin de ligne]{espace}s qui pr�c�dent la marque de \idx{fin de ligne} sont supprim�s en m�me temps que cette marque et \TeX{} ins�re � la place un caract�re sp�cial dont le code de caract�re est contenu dans la primitive \idx\endlinechar. Habituellement, ce code vaut \number`\^^M{}, celui du caract�re retour charriot\verbidx*[ (retour charriot)]{^^M}.

\label{catcode.5}
\begin{regle}
Dans la ligne courante, si un caract�re de catcode \number\catcode`\%\relax{} (caract�re de commentaire, g�n�ralement \cidx[ (caract�re de commentaire)]\%) ou \number\catcode`\^^M\relax{} (retour charriot, g�n�ralement \verb|^^M|\verbidx*[ (retour charriot)]{^^M}) apparait, alors, ce caract�re ainsi que tout ce qui va jusqu'� la fin de la ligne est ignor�, y compris le caract�re de code \idx\endlinechar ins�r� � la fin de la ligne.
\end{regle}

Les caract�res de catcode 5 ob�issent � une r�gle particuli�re :

\label{regle.catcode5}\begin{regle}
Un caract�re de catcode 5 est interpr�t� comme un \idx[!catcode 5]{espace}.\idx*{catcode!5 (retour charriot)}\idx*{espace!catcode 5}

Deux caract�res de catcode 5 cons�cutifs sont transform�s en la s�quence de contr�le \idx\par\verbidx*[ cons�cutifs]{^^M}.
\medbreak

Cela signifie qu'un retour charriot\verbidx*[ (retour charriot)]{^^M} est vu comme un \idx[!fin de ligne]{espace}, sauf s'il est pr�c�d� du caract�re \cidx\% et que deux retours charriots cons�cutifs (symbolis�s dans le code source par une ligne vide) seront �quivalents � \idx\par.
\end{regle}

On peut localement modifier le caract�re de code \idx\endlinechar pour obtenir des effets sp�ciaux en tenant compte de la r�gle suivante :

\begin{regle}
Si \idx\endlinechar est n�gatif ou sup�rieur � 255, aucun caract�re n'est ins�r� aux fins de lignes.
\end{regle}

Voici une illustration de cette r�gle o� l'on teste le comportement normal, puis on met \idx\endlinechar � $-1$ et enfin � \number`\X{} (qui est le code de caract�re de �X�) :

{\endlinechar13
\showcode|%%% comportement normal %%%
a) comportement normal :
Ligne 1
Ligne 2

Ligne 3
\medbreak�\idx*\medbreak�
b) Aucun caract�re de fin de ligne :�\idx*{caract�re de fin de ligne}�
%%% aucune insertion en fin de ligne %%%
\endlinechar=-1 �\idx*\endlinechar�
Ligne 1
Ligne 2

Ligne 3\endlinechar13

\medbreak�\idx*\medbreak�
c) "X" comme caract�re de fin de ligne :�\idx*{caract�re de fin de ligne}�
%%% "X" est ins�r� � chaque fin de ligne
\endlinechar=88
Ligne 1
Ligne 2

Ligne 3|}

On peut notamment remarquer que lorsque \idx\endlinechar est n�gatif, tout se passe comme si les lignes se terminaient toutes par le \idx[|voir{�\texttt{\char37}�}]{caract�re de commentaire} \cidx\%, de catcode \number\catcode`\%.

\chapter{Octets dont le bit de poids fort est 1}
Venons-en maintenant � la partie de la table des caract�res qui se situe apr�s le num�ro 128, c'est-�-dire dont la repr�sentation en base 2 est \bin{1xxxxxxx} et dont le bit le le plus � gauche, celui qui a le plus de �poids\footnote{Dans l'�criture moderne des nombres, dite �de position�, les chiffres ont une influence li�e � leur position dans le nombre. En �criture d�cimale, nous avons pris comme convention qu'un nombre, par exemple �crit avec 3 chiffres �$\overline{\text{\textit{abc}}}$�, est �gal � la somme $a\times100+b\times10+c\times1$. Le coefficient d'un chiffre (ou son �poids�) est une puissance de 10 dont l'exposant est d'autant plus grand que la place du chiffre est � gauche : $10^2$, $10^1$ et $10^0$. On dit que le chiffre $a$ a un �poids� fort puisque plus important que celui des chiffres $b$ ou $c$.

En binaire, c'est le m�me principe sauf que les poids sont les puissances de 2. Si un \idx{octet} s'�crit $\overline{\text{\textit{abcdefgh}}}$, sa valeur en base 10 est $a\times2^7+b\times2^6+\cdots+g\times2^1+h\times2^0$. Le bit \bin{a} est le bit de poids fort tandis que \bin{h} est celui de poids faible.}�, vaut 1. Cette partie de la table n'est pas dans la convention ASCII et donc, d�pend de la convention que l'on veut se donner. Pour nous en France, deux de ces conventions sont utilis�es et d�pendent du codage avec lequel a �t� enregistr� le code source. Comme on l'a dit, cet \idx{encodage} doit �tre un surensemble de l'ASCII qui est commun � tous les \idx{encodage}s.

Historiquement, plusieurs fa�ons de compl�ter la table ASCII ont vu le jour, chacune donnant naissance � un \idx{encodage} � part enti�re. Aucune harmonisation n'a jamais �t� faite et plusieurs \idx{encodage}s sur 8 bits cohabitent encore � l'heure actuelle. Les plus connus pour les langues occidentales sont :

\begin{itemize}
       \item \texttt{ansinew} a �merg� comme \idx{encodage} des syst�mes d'exploitation Windows;
       \item \texttt{applemac} a �t� choisi dans la sph�re de la marque Apple jusqu'� un pass� r�cent;
       \item \texttt{latin1}\idx*[|(]{encodage!latin1} a �t� utilis� dans le monde Unix/Linux.
\end{itemize}

Selon ces trois encodages, le caract�re �� est respectivement plac� � l'octet \Hex{E9}, \Hex{8E} et \Hex{E9}.
\grandsaut

Int�ressons-nous � l'\idx{encodage} �\latin� ou �\hbox{ISO 8859-1}�\idx*{encodage!latin1}. Cet \idx{encodage} a �t� cr�� pour �tre utilis� avec les langues europ�ennes. Par exemple, l'octet \number"E0{} (ou \Hex{E0} en hexad�cimal) code la lettre ��. On dispose ainsi de tous les caract�res n�cessaires pour la langue fran�aise\footnote{� l'exception notable de �\oe �, �\OE � et �\"Y�. Il manque �galement quelques caract�res pour d'autres langues.}. Il faut noter que l'extension pour \LaTeX{} �\verb-inputenc-�\idx*{package!inputenc} charg�e avec l'option �\verb-latin1-� rend plusieurs caract�res actifs (et donc met leur catcode � 13) lorsque l'\idx{encodage} est \latin\idx*{encodage!latin1}. Le caract�re �� en fait partie et donc, ce caract�re se comporte comme une commande : \verb-inputenc- lui fait ex�cuter un code qui au final, imprime le caract�re ��. Il est imm�diat que du fait qu'il est actif, le caract�re �� n'appartient pas � la cat�gorie des lettres.

Voici la table de l'\idx{encodage} \latin. Seuls les \idx{octet}s sup�rieurs ou �gaux � 128 y figurent puisque ceux qui sont inf�rieurs � 128 sont ceux de la table ASCII :

\begin{centrage}
       \catcode`\�=12
       \tabcolsep0pt
       \footnotesize
       \par\noindent
       \def\?#1{\ttfamily\bfseries x#1}%
       \charcnt=\numexpr128-17
       \def\:{\global\advance\charcnt1 }%
       \def\!{\cellcolor{gray!40}}%
       \let\^\carnonaff% marque un caract�re non affichable
       \newcolumntype G{m{\dimexpr(\linewidth-18\arrayrulewidth)/17\relax}}%
       \begin{tabular}{|@{}>{\columncolor{gray!40}[0pt][0pt]\hfill\ttfamily\bfseries}G<{x\hfill\null}@{}|*{16}{@{}>{\:\hfill\vrule height3.3ex depth.8ex width0pt }G<{\hfill\unless\ifnum\charcnt<128 \vtop{\kern1.5pt\normalfont\tiny\llap{\number\charcnt\kern.5pt}\kern1pt}\fi\null}@{}|}}
       \hline
               \rowcolor{gray!40}[0pt][0pt]\multicolumn1{|@{}G@{}|}{\cellcolor{white}}
               &\?0 &\?1 &\?2 &\?3 &\?4 &\?5 &\?6 &\?7 &\?8 &\?9 & \?A& \?B&\?C &\?D &\?E &\?F \\\hline
               8 & \^PAD& \^HOP&\^BPH &\^NBH &\^IND &\^NEL &\^SSA &\^ESA &\^HTS &\^HTJ &\^VTS &\^PLD &\^PLU &\^RI  &\^SS2 &\^SS3 \\\hline
               9 & \^DCS& \^PU1& \^PU2& \^STS& \^CCH& \^MW &\^SPA& \^EPA& \^SOS& \^SGCI& \^SCI&\^CSI &\^ST  &\^OSC &\^PM & \^APC\\\hline
               A &\scalebox{0.8}[1]{NBSP}&^^a1&^^a2&^^a3&^^a4&^^a5&^^a6&\oldparagraph&^^a8&^^a9&^^aa&^^ab&\!$^^ac$&-&^^ae&^^af \\\hline
               B &^^b0&\!$^^b1$&\!$^^b2$&\!$^^b3$&^^b4&\!$^^b5$&$^^b6$&^^b7&^^b8&\!$^^b9$&^^ba&^^bb&^^bc&^^bd&^^be&^^bf\\\hline
               C &^^c0&^^c1&^^c2&^^c3&^^c4&^^c5&^^c6&^^c7&^^c8&^^c9&^^ca&^^cb&^^cc&^^cd&^^ce&^^cf\\\hline
               D &^^d0&^^d1&^^d2&^^d3&^^d4&^^d5&^^d6&\!$^^d7$&^^d8&^^d9&^^da&^^db&^^dc&^^dd&^^de&^^df\\\hline
               E &^^e0&^^e1&^^e2&^^e3&^^e4&^^e5&^^e6&^^e7&^^e8&^^e9&^^ea&^^eb&^^ec&^^ed&^^ee&^^ef\\\hline
               F &^^f0&^^f1&^^f2&^^f3&^^f4&^^f5&^^f6&\!$^^f7$&^^f8&^^f9&^^fa&^^fb&^^fc&^^fd&^^fe&^^ff\\\hline
       \end{tabular}
\end{centrage}
\grandsaut

Ici encore, cette partie de la table comporte des caract�res non affichables. Ils se situent entre les codes \Hex{80} et \Hex{9F} inclus auxquels il faut rajouter le caract�re de code \Hex{AD}. Ceux qui se trouvent dans des cases gris�es sont affichables, mais ils doivent �tre utilis�s en mode math�matique\idx*{mode!math�matique}.
\grandsaut

Bien s�r, certains de ces caract�res ne sont pas directement accessibles au clavier. En fait, les caract�res accessibles au clavier d�pendent de la configuration de chacun. Par exemple, sur \emph{mon} clavier, avec \emph{mon} syst�me d'exploitation et le pilote correspondant au mod�le du clavier, avec le mappage du clavier s�lectionn� dans les options du syst�me d'exploitation, je peux acc�der au caract�re �\texttt� avec la combinaison de touches \bioLegacyKeyGlyph{A_l_t_G_r}+\bioLegacyKeyGlyph{A}. Pour le caract�re �$�$�, c'est avec \bioLegacyKeyGlyph{A_l_t_G_r}+\bioLegacyKeyGlyph{R}. Et ainsi de suite\ldots{} En revanche, certains caract�res dans la table ci-dessus me sont inaccessibles, sauf � les taper via \verb-^^-.
\grandsaut

L'\idx{encodage} �\utf\idx*[|(]{encodage!UTF8}\footnote{L'acronyme \texttt{UTF8} signifie �Unicode Transformation Format 8 bits�.}� permet de coder beaucoup plus que 256 caract�res avec l'in�vitable cons�quence que certains d'entre eux seront cod�s sur plusieurs octets. Le principe de cet \idx{encodage} est assez simple et on peut le d�crire ici :
\begin{itemize}
       \item si un caract�re a un code inf�rieur � 128, alors il est cod� par le m�me \idx{octet} que dans le \idx{encodage} ASCII;
       \item sinon, il est cod� sur plusieurs octets : le nombre de bits de poids fort non nuls (au maximum 4) du premier octet indique le nombre d'octets pris au total pour l'\idx{encodage} du caract�re. Par exemple, si un \idx{octet} vaut \bin{1110xxxx} en binaire, les 3 bits de poids fort suivis d'un 0 indiquent que ce caract�re est cod� sur 3 octets, les 2 octets restants ayant obligatoirement les bits de poids fort \bin{10}, c'est-�-dire qu'ils sont de la forme \bin{10xxxxxx}.

       Finalement, ce caract�re sera donc cod� sur 3 octets ayant cette forme : \bin{1110xxxx 10xxxxxx 10xxxxxx}. Il y a donc 16 bits non contraints sur 24. Le �code propre� du caract�re sera constitu� des 16 bits \bin x.
\end{itemize}

Si l'on s'int�resse par exemple au caract�re ��, celui-ci est cod� en \utf par les 2 octets \Hex{C3} \Hex{A0}. �crits en binaire, on obtient \bin{\textbf{110}00011} \bin{\textbf{10}100000} o� les bits contraints sont �crits en gras. Il en r�sulte que le code propre du caract�re �� est \bin{00011100000}. Si on �limine les z�ros inutiles de gauche, on obtient \bin{11100000} qui est l'\idx{octet} \Hex{E0}, celui que l'on retrouve dans la table de l'\idx{encodage} \latin pour la lettre ��. En effet, en \utf, les caract�res ayant des codes propres compris entre 128 et 255 \emph{doivent} �tre les m�mes que les caract�res qui ont ces codes dans la table de \latin. Enfin, le symbole �\geneuro� est cod� sur 3 \idx{octet}s en UFT8 : \Hex{E2} \Hex{82} \Hex{AC} qui s'�crit en binaire \bin{\textbf{1110}0010} \bin{\textbf{10}000010} \bin{\textbf{10}101100} et qui donne un code propre de \bin{10000010101100} soit \Hex{20AC}.

Pour \TeX{}, le principe est le m�me qu'avec l'\idx{encodage} \latin, il faut rendre actifs tous les \idx{octet}s qui ont une �criture binaire \bin{110xxxxx} ou \bin{1110xxxx}  ou \bin{11110xxx} et dont les bits non contraints �\bin x� correspondent au d�but du code des caract�res que \TeX{} va prendre en charge. Ensuite, ces caract�res actifs vont lire le (ou les) \idx{octet}(s) suivant(s) et traduire le tout de fa�on � faire imprimer le caract�re voulu.
\grandsaut

Ce qu'il faut retenir est que, aussi bien en \latin qu'en \utf, les lettres accentu�es et les caract�res ne figurant pas dans la table ASCII ne sont pas des octets dont le code de cat�gorie est 11 et n'appartiennent donc pas � la cat�gorie des lettres. De plus, pour ceux qui utilisent l'\idx{encodage} \utf qui tend � devenir la norme, il ne faut pas perdre de vue que lorsqu'on �crit la lettre �� dans le code, nous ne voyons qu'un seul caract�re, mais celui-ci est stock� sur \emph{deux} octets dans le fichier et donc, \TeX{} voit \emph{deux} choses. Il n'y a donc pas �quivalence entre �octet� et �caract�re� et dans tous les cas, \TeX{} ne lit pas le code caract�re par caract�re, mais octet par octet.

Cette derni�re affirmation n'est vraie que pour les trois moteurs \TeX{} (celui �crit par \idx*{Knuth Donald}Donald~\textsc{Knuth}), $\varepsilon$\TeX{}\idx*{moteur!etex} et pdf\TeX{}\idx*{moteur!pdftex}. Outre ces � anc�tres �, encore majoritairement utilis�s malgr� leur �ge, il existe d�sormais des moteurs plus r�cents qui g�rent nativement l'\idx{encodage} \utf : \XeTeX{} et lua\TeX{}. Ces deux moteurs, entre autres possibilit�s, lisent le code source caract�re \utf par caract�re \utf et il peut donc arriver que plusieurs octets soient lus en un coup pour former une entit� unique. Malgr� le progr�s que cela constitue, on consid�rera dans ce livre que l'on utilise un moteur fonctionnant octet par \idx{octet}.\idx*[|)]{encodage!UTF8}\idx*[|)]{encodage!latin1}

\chapter{Codes de cat�gorie}\idx*[|(]{catcode}\idx*[|(]{\catcode}
Le sujet est vaste et technique puisqu'il touche � l'un des m�canismes les plus intimes de \TeX. Nous nous contenterons pour l'instant de voir l'essentiel, quitte � y revenir plus loin au fur et � mesure de nos besoins. Rappelons que les �cat�gories� de \TeX{} sont au nombre de 16 et regroupent des caract�res ayant des propri�t�s communes aux yeux de \TeX{}. Le code de cat�gorie d'un octet lu est la premi�re chose que \TeX{} examine, avant m�me le nombre correspondant � l'octet lui-m�me puisque le code de cat�gorie d�termine la fa�on dont \TeX{} doit r�agir face � cet \idx{octet}.
\grandsaut

Tout d'abord, pour acc�der au code de cat�gorie d'un caract�re, il faut utiliser la primitive \idx\catcode suivie du \emph{\idx{code de caract�re}}. L'ensemble constitue une repr�sentation interne de l'entier �tant le code de cat�gorie du caract�re concern�. La commande \idx\number\label{number} convertit la repr�sentation interne d'un nombre en la repr�sentation affichable habituelle, c'est-�-dire en base 10 et en chiffres arabes. Par exemple, si on veut afficher le code de cat�gorie de �\cidx\$� dont le code de caract�re est \number`\$, on va �crire �\verb-\number\catcode36-� et on obtiendra �\number\catcode36 �.

On peut trouver g�nant de mettre explicitement le code du caract�re apr�s la primitive \idx\catcode. En effet, cela oblige � aller le chercher dans la table des caract�res ASCII puis le convertir en d�cimal. Cette derni�re �tape, la conversion hexad�cimal vers d�cimal, n'a pas lieu d'�tre faite car \TeX{} comprend nativement les nombres hexad�cimaux\footnote{O� les lettres qui le composent \emph{doivent} �tre majuscules.}. Pour indiquer qu'un nombre est �crit en base 16, il faut le faire pr�c�der du caract�re �\cidx[ (notation hexad�cimale)]\"� et pour traduire le tout en nombre en �criture arabe en base 10, il faut mettre devant l'ensemble la primitive \idx\number{}:

\showcode/a) \number"1A \qquad b) \number"AB3FE \qquad c) \number"78 �\idx*\number\idx*\qquad�/

Pour obtenir le code de cat�gorie du caract�re �\cidx\$� dont le code de caract�re est \Hex{24}, on peut donc �crire \verb-\number\catcode"24-.

Dans le m�me ordre d'id�e et bien que cela soit assez rarement utile, il faut savoir que \TeX{} comprend aussi les nombres en notation \emph{octale}, c'est-�-dire �crits en base 8. Pour indiquer qu'un nombre est �crit en base 8, il faut le faire pr�c�der de l'apostrophe �\cidx[ (notation octale)]\'� :

\showcode/a) \number'15 \qquad b) \number'674 \qquad c) \number'46�\idx*\number\idx*\qquad�/

Malgr� ce c�t� pratique, il faut toujours aller voir la table ASCII pour chercher le code de caract�re. Heureusement, on peut facilement convertir un caract�re en son code �crit en base 10. Pour cela, s'agissant des caract�res de catcode 11\idx*{catcode!11 (lettre)} ou 12\idx*{catcode!12 (autre)}, il faut faire pr�c�der le caract�re de l'apostrophe inverse \boxtoken{`}\cidx*[ (notation de nombre)]{\`} ce qui donnerait �\verb-\number`a-� pour afficher le code de caract�re de �a�. Un moyen encore plus s�r qui fonctionne pour \emph{tous} les caract�res, quels que soient leurs catcodes, est de faire pr�c�der le caract�re de l'apostrophe inverse \emph{et} du caract�re d'�chappement comme dans cet exemple:

\showcode/a) \number`\a \quad %code de caract�re de "a"�\idx*\number\idx*\quad�
b) \number`\\ \quad % code de caract�re de "\"
c) \number`\$ \quad % code de caract�re de "$"
d) \number`\  \quad % code de caract�re de l'espace
e) \number`\5 \quad % code de caract�re de "5"
f) \number`\{ \quad % code de caract�re de l'accolade ouvrante
g) \number`\}       % code de caract�re de accolade fermante/

Il devient facile d'afficher le code de cat�gorie de n'importe quel caract�re :

\showcode/a) \number\catcode`\a \quad %code de cat�gorie de "a"�\idx*\catcode�
b) \number\catcode`\\ \quad % code de cat�gorie de "\"�\idx*\number�
c) \number\catcode`\$ \quad % code de cat�gorie de "$"
d) \number\catcode`\  \quad % code de cat�gorie de l'espace
e) \number\catcode`\5 \quad % code de cat�gorie de "5"
f) \number\catcode`\{ \quad % code de cat�gorie de l'accolade ouvrante�\idx*\quad�
g) \number\catcode`\}       % code de cat�gorie de accolade fermante/

Afficher un code de cat�gorie n'est pas r�ellement utile. Ce qui l'est plus est de \emph{modifier} le code de cat�gorie d'un caract�re, nous verrons dans quels buts plus loin. Pour ce faire, on �crit\idx*{\catcode} :
\centrecode-\catcode`\<caract�re>=<nombre>-

\noindent o� \verb-<nombre>- est un entier de 0 � 15. Apr�s que \TeX{} a ex�cut� ce code, � chaque fois que \TeX{} lira le \verb-<caract�re>-, il lui assignera le code de cat�gorie �gal au \verb-<nombre>-. Supposons par exemple que nous souhaitions que le caract�re �\verb|W|� ne soit plus dans la cat�gorie des lettres, mais rev�te le code de cat�gorie de 3 pour utiliser indiff�remment �\verb|W|� ou �\cidx\$� pour basculer en mode math�matique\idx*{mode!math�matique}. Voici comment proc�der :

\showcode/Ici, W est une lettre...\par
\catcode`\W=3 % W devient le signe de bascule en mode math�\idx*\catcode\idx*{mode!math�matique}�
Wx+y=3W\par
$a+b=cW\par
W2^3=8$\par
\catcode`\W=11 % W redevient une lettre�\idx*\catcode�
De nouveau, W est une lettre.../

Il est important de restaurer le code de cat�gorie initial � la fin de la zone o� l'on souhaite avoir le comportement voulu sous peine de s'exposer � des erreurs de compilation ou des effets ind�sirables plus tard.

Sym�triquement, on aurait aussi bien pu assigner le code de cat�gorie 11 (ou 12) au caract�re �\verb-$-� de fa�on � pouvoir l'afficher comme on le fait d'une lettre ou d'un caract�re affichable :
\showcode/$3+4=7$ \par % $ est la bascule math
\catcode`\$=12 % $ devient un caract�re affichable�\idx*\catcode�
$ s'affiche sans probl�me : $\par
\catcode`\$=3 % $ redevient la bascule math�\idx*\catcode�
$4+3=7$/

\begin{exercice}
Inventer un proc�d� pour que, dans une zone, seuls les premiers mots de chaque ligne soient affich�s.
\solution
Il suffit de modifier le code de cat�gorie de l'\idx[!catcode 5]{espace} pour qu'il devienne 5. D'apr�s la r�gle vue � la page~\pageref{catcode.5}, dans une ligne, tout ce qui se trouve apr�s un caract�re de catcode 5\idx*{catcode!5 (retour charriot)} est ignor� :

\showcode|Voici les premiers mots de chaque ligne :

\catcode`\ =5 % l'espace est d�ormais de catcode 5�\idx*\catcode�
Cette premi�re ligne sera tronqu�e...

La deuxi�me aussi !

Et la derni�re �galement.
\catcode`\ =10 % l'espace reprend son catcode�\idx*\catcode�

Le comportement normal est restaur�.|
\end{exercice}

Il faut retenir que les codes de cat�gorie attach�s � chaque caract�re de la table des catcodes de la page~\pageref{catcode.table} ne sont que des valeurs \emph{par d�faut} qui peuvent �tre facilement modifi�es comme on l'a vu dans les exemples pr�c�dents. On peut donc parler de �r�gime de catcode�, c'est-�-dire qu'� chaque moment, chacun des 256 octets aura un catcode qui lui sera attribu�. En r�gle g�n�rale, si l'on modifie le catcode d'un octet, il est sage de restaurer les codes de cat�gorie de la table des catcodes au-del� de la zone o� l'on veut faire des modifications. En effet, il est admis que les catcodes �naturels� de cette table doivent rester la r�gle.\idx*[|)]{catcode}\idx*[|)]{\catcode}
%|                                                                            |
%|                                Fin partie 1                                |
%|____________________________________________________________________________|

% ____________________________________________________________________________
%|                                                                            |
%|                                  Partie 2                                  |
%|                                                                            |
\defpartcomment{\lettrine[lines=3,nindent=0pt]{\libertineInitialGlyph{D}}{ans} cette partie, nous allons nous int�resser � ce qui fait l'essentiel du code lorsqu'on programme, les commandes. Contrairement � d'autres langages de programmation o� leur comportement est assez intuitif, elles rev�tent avec \TeX{} des propri�t�s originales. Par leur interm�diaire, nous d�couvrirons l'essentiel de ce qu'il faut savoir pour commencer � programmer c'est-�-dire la fa�on intrins�que qu'a \TeX{} de fonctionner et comment contr�ler ce fonctionnement. Apr�s ces pr�requis, nous pourrons alors aborder la partie suivante o� nous commencerons les premiers exercices de programmation.}
\part{Commandes}

\chapter[\Qu 'est-ce qu'une commande ?]{Qu'est-ce qu'une commande ?}
Lorsqu'on utilise \TeX{}, les s�quences de contr�le\idx*{s�quence de contr�le} sont des mots constitu�s de lettres (caract�res de catcode 11) qui d�butent par le \idx{caract�re d'�chappement} �\cidx[ (caract�re d'�chappement)]\\�. Ce caract�re sp�cial peut �tre chang� pour en utiliser un autre, mais cette man\-\oe uvre ne sera pas d�crite pour l'instant. Ainsi, lorsque \TeX{} lit le code que l'on a tap�, toujours lin�airement de gauche � droite, forme une \idx{s�quence de contr�le} � l'aide des lettres, majuscules ou minuscules, qui suivent le caract�re d'�chappement �\cidx\\�, la casse �tant prise en compte. \TeX{} consid�re que le nom de la \idx{s�quence de contr�le} se termine au dernier caract�re qui est une lettre . Une fois que ce nom est construit, il devient une entit� unitaire indivisible, une �unit� lexicale� ou �\emph{\idx{token}}� au m�me titre qu'un \idx{octet} dans le code si celui-ci ne sert pas � �crire une \idx{s�quence de contr�le}.

\begin{regle}
Une \idx{s�quence de contr�le} commence par le caract�re d'�chappement de catcode 0\idx*{catcode!0 (caract�re d'�chappement)} qui est habituellement �\cidx\\� et se termine � la fin de la plus longue s�rie de lettres (caract�res de catcode 11\idx*{catcode!11 (lettre)}) qui le suit.
\end{regle}

Les s�quences de contr�le sont de deux types :
\begin{itemize}
       \item les �commandes�, que l'on appellera aussi �macros�, ont �t� d�finies soit par l'utilisateur, par un format ou par une extension. Ces commandes ont un \idx{texte de remplacement}, c'est le code \TeX{} qui les d�finit, ou si l'on pr�f�re, le code \TeX{} qu'elles �contiennent�. Ce texte de remplacement peut �videmment contenir d'autres s�quences de contr�le ;
       \item les \idx{primitive}s, qui sont cod�es en dur dans le programme binaire \texttt{tex}, et qui repr�sentent en fait le �vocabulaire� de base avec lequel on doit se d�brouiller pour faire tout le reste. Les primitives n'ont pas de \idx{texte de remplacement} et sont destin�es � �tre ex�cut�es de fa�on binaire par le programme \texttt{tex}.
\end{itemize}

\label{regle.espace}\begin{regle}
Voici des r�gles concernant les espaces et les s�quences de contr�le :
       \begin{enumerate}
               \item dans le code qui est tap�, tout \idx{espace} qui suit une unit� lexicale de type \idx{s�quence de contr�le} est ignor�;
               \item si plusieurs espaces \idx*{espace!cons�cutifs}se suivent \emph{dans le code}, seul le premier est pris en compte et les autres sont ignor�s (ceci est un rappel de la r�gle page~\pageref{espaces.consecutifs});
               \item il d�coule des deux premiers points que, quel que soit le nombre d'espaces qui suivent une \idx{s�quence de contr�le}, ceux-ci sont ignor�s.
       \end{enumerate}
\end{regle}

Lorsqu'un utilisateur d�finit une commande, il lui donne un \emph{\idx{texte de remplacement}} qui sera utilis� � la place de cette commande lorsqu'elle sera � ex�cut�e � par \TeX{}. La primitive qui permet de d�finir ce texte de remplacement est �\idx[|(]\def�. Elle doit �tre suivie du nom de la commande et du texte de remplacement entre \idx{accolade}s :

\centrecode-\def\foo{Bonjour}-

Apr�s cette d�finition, � chaque fois que \TeX{} �ex�cutera� le token \verb|\foo| dans le code source, il le remplacera dans sa m�moire par son texte de remplacement qui est �Bonjour� et continuera � lire le code obtenu en tenant compte de ce remplacement. Cet endroit dans sa m�moire s'appelle �\idx{pile d'entr�e}�. Pour �crire un espace apr�s \verb-\foo- qui ne soit pas ignor�, il faut trouver un moyen, invisible � l'affichage, pour que l'espace affich� apr�s la macro ne lui soit pas cons�cutif. On peut envelopper la macro dans des accolades ou la faire suivre de \verb-{}-\cidx*\{\cidx*\} de fa�on � ce que l'espace se situant \emph{apr�s} l'accolade fermante ne soit pas ignor� comme il le serait apr�s une \idx{s�quence de contr�le}. On peut �galement mettre apr�s \verb|\foo| la macro \idx\space dont le \idx{texte de remplacement} est un espace. Dans ce cas, le dernier point de la r�gle pr�c�dente ne s'applique pas, car ce qui suit \verb|\foo| n'est pas un espace mais une \idx{s�quence de contr�le}, et peu importe son texte de remplacement.

\showcode/\def\foo{Bonjour}% d�finit le texte de remplacement de \foo
a) \foo Alice.\qquad% espace ignor�\idx*\qquad�
b) {\foo} Bob.\qquad% espace non ignor�
c) \foo{} Chris.\qquad% espace non ignor�
d) \foo\space Daniel.% \space est remplac� par un espace�\idx*\space�/

\begin{regle}
Lorsque \TeX{} assigne un \idx{texte de remplacement} � une macro avec \idx\def, ce texte de remplacement n'est pas ex�cut�, il est juste converti en \idx{token}s et rang� quelque part dans la m�moire de \TeX{} pour �tre ressorti plus tard pour venir en replacement de la macro, et �ventuellement �tre ex�cut� � ce moment.

Le texte de remplacement est tr�s peu \emph{analys�} lorsqu'il est stock� avec \verb|\def|, ce qui veut dire que si une erreur est contenue dans le texte de remplacement, elle ne sera pas d�tect�e au moment o� \idx\def agit mais plus tard lors du remplacement et de l'ex�cution proprement dite.

Une des rares choses que \TeX{} v�rifie dans le \idx{texte de remplacement} d'une macro est qu'un caract�re de \idx*[!15 (invalide)]{\catcode}catcode 15\idx*{catcode!15 (invalide)} n'y figure pas (nous verrons plus loin les autres v�rifications que \TeX{} effectue).
\end{regle}

\section{Accolades et groupes}
Les \cidx*\{\cidx*\{\idx{accolade}s des lignes 3 et 4 d�limitent des �\idx[|(]{groupe}s\footnote{On dit aussi parfois �\idx[!simple]{groupe} simple�.}�. Un groupe est une zone o� les modifications effectu�es et o� les d�finitions faites restent \emph{locales} � ce groupe et sont d�truites lors de sa fermeture pour revenir � l'�tat ant�rieur � l'ouverture du groupe. En revanche, les \idx{accolade}s obligatoires utilis�es avec la primitive \idx\def de la ligne 1 ne d�limitent pas un groupe. Elles d�limitent la port�e du \idx{texte de remplacement}. On peut donc consid�rer qu'il y a deux types d'\idx{accolade}s. D'une part celles qui sont obligatoires et font partie de la syntaxe d'une primitive comme celles de la primitive \idx\def qui d�limitent le \idx{texte de remplacement} et d'autre part celles, non obligatoires, qui servent de fronti�res � un groupe.

Un \idx[!semi-simple]{groupe} semi-simple\footnote{Le nom � groupe simple � �tant d�j� pris pour les groupes entre accolades, il y a fort � parier que D.~\textsc{Knuth}, par jeu et par affinit� pour les math�matiques, ait baptis� � groupe semi-simple� un groupe d�limit� par \texttt{\textbackslash begingroup} et \texttt{\textbackslash endgroup}.} est compris entre les instants o� \TeX{} ex�cute les primitives \idx\begingroup et \idx\endgroup. Comme dans les groupes, les modifications et les d�finitions dans un groupe semi-simple sont locales et sont restaur�es � leur �tat ant�rieur � sa fermeture.

\begin{regle}
On peut cr�er des zones o� les modifications faites aux macros et autres param�tres de \TeX{} sont locales. Ces zones portent le nom de \idx{groupe}s.

Un \idx{groupe} est d�limit� :
\begin{itemize}
       \item soit par une \idx{accolade} ouvrante et une accolade fermante auquel cas le groupe est qualifi� de � simple � ;
       \item soit par les primitives \idx\begingroup et \idx\endgroup et dans ce cas, le groupe est dit � semi-simple�.
\end{itemize}
Il est entendu qu'un groupe ouvert avec une accolade ne peut �tre ferm� qu'avec une accolade et il en est de m�me avec \idx\begingroup et \idx\endgroup.

� l'int�rieur d'un groupe, les assignations sont locales � ce groupe et sont restaur�es � leur �tat ant�rieur lors de la fermeture du groupe. Pour qu'une assignation soit \emph{globale}, c'est-�-dire pour qu'elle survive � la fermeture du groupe, il faut faire pr�c�der la commande d'assignation de la primitive \idx\global.

Les groupes d�limit�s par accolades et les groupes semi-simples peuvent �tre emboit�s, mais \emph{ne doivent pas} se chevaucher.
\end{regle}

\begin{exercice}
Puisqu'un groupe d�limit� par accolades et un groupe semi-simple ont les m�mes fonctionnalit�s, pourquoi existe-t-il deux fa�ons diff�rentes de d�limiter un groupe ?
\solution
Tout d'abord, abondance de biens ne nuit pas !

Ensuite, il y a des cas o� une \idx{accolade} ne peut pas d�limiter un d�but ou une fin groupe, c'est dans le texte de remplacement d'une macro. Par exemple, si l'on voulait qu'une macro \verb|\startbold| ouvre un groupe et �crive en gras et que la macro \verb|\stopbold| stoppe ce fonctionnement, on serait oblig� d'utiliser \idx\begingroup et \idx\endgroup :

\showcode|\def\startbold{\begingroup \bf}
\def\stopbold{\endgroup}
Voici \startbold du texte en gras\stopbold{} et la suite.|

En effet, cela constituerait une erreur que d'�crire :

\centrecode|\def\startbold{{\bf}
\def\stopbold{}}|

\noindent car le texte de remplacement de \verb|\startbold| irait jusqu'� la prochaine accolade �quilibr�e et serait

\centrecode|{\bf} \def\stopbold{}|

\noindent Il n'y aurait pas d'erreur de compilation, mais la port�e de \verb|\bf| serait nulle puisque cette macro est seule dans son groupe et \verb|\stopbold|, ayant un texte de remplacement vide, n'aurait aucune action.
\end{exercice}

\begin{exercice}
D�crire ce qui se passe exactement et quel va �tre l'affichage si l'on d�finit une macro \verb|\foo| dans ce contexte :

\centrecode-\begingroup
\def\foo{Hello \endgroup world !}
\foo-

\solution
D�j�, la d�finition sera \emph{locale} au groupe semi-simple initi� par \idx\begingroup et la macro \verb|\foo| sera d�truite d�s qu'un \idx\endgroup sera ex�cut� pour revenir � ce qu'elle �tait avant le groupe semi-simple (�ventuellement ind�finie). Le \idx\endgroup de la ligne 2 n'est pas �ex�cut� par \TeX{} puisque ce \idx\endgroup est stock� dans le \idx{texte de remplacement} de la macro \verb|\foo|. Il ne ferme donc pas le groupe semi-simple lorsque \TeX {} ex�cute la ligne \no2 du code.

Lorsque \TeX{} rencontre \verb|\foo| � la 3\ieme{} ligne du code, il se trouve toujours dans le groupe semi-simple ouvert par \idx\begingroup et la d�finition faite la ligne au-dessus est toujours en vigueur. \TeX{} remplace donc \verb|\foo| par son texte de remplacement, ce remplacement se faisant dans la \idx{pile d'entr�e} de \TeX{} :

\centrecode-Hello \endgroup world !-

\noindent \TeX{} va continuer � lire ce qu'il y a dans sa pile et va donc afficher \verb*|Hello | puis, en rencontrant \idx\endgroup, d�truira la d�finition locale de \verb|\foo| enfin continuera � lire ce qui est dans sa pile et affichera : \verb|world !|.

On voit donc que dans ce cas, la macro \verb|\foo| porte dans son \idx{texte de remplacement} la primitive \idx\endgroup qui provoquera son autodestruction !\idx*[|)]{groupe}\idx*[|)]\def
\end{exercice}

\begin{regle}
La primitive \idx\aftergroup\verb|<token>| permet de stocker un \verb|<token>| dans une pile sp�ciale de la m�moire de \TeX pour que ce \idx{token} soit lu et ex�cut� juste apr�s �tre sorti du groupe courant, que ce groupe soit simple ou semi-simple.

Si plusieurs commandes \idx\aftergroup sont rencontr�es dans un m�me groupe, les \idx{token}s mis en m�moire seront lus dans l'ordre o� ils ont �t� d�finis. Ainsi, �crire

\centrecode-\aftergroup<x>\aftergroup<y>-\idx*\aftergroup

se traduira par �\verb|<x><y>|� apr�s la fermeture du groupe.
\end{regle}

\showcode/\def\foo{foo}
\begingroup A\aftergroup\foo B\endgroup\par
{A\aftergroup X\aftergroup\foo B}/

La primitive \idx\aftergroup trouve une utilit� lorsque la composition en italique est demand�e dans un groupe (qui en d�limite la port�e). En effet, pour �viter que le dernier caract�re en italique (qui est donc pench� vers la droite) ne soit trop pr�s du caract�re du mot suivant (qui est vertical), il convient d'ins�rer � la fin du groupe une \idx{correction d'italique}, surtout si les deux caract�res sont des lettres hautes comme �l�, �f� ou une parenth�se fermante. Cette correction, effectu�e en \TeX{} par la primitive \idx[ (correction d'italique)]\/, augmente l�g�rement l'espace entre ces deux caract�res. La diff�rence est tr�s fine, mais elle existe :

\showcode|1) (un {\it cheval})\par% sans correction d'italique�\idx*\it�
2) (un {\it\aftergroup\/cheval})\par% avec correction d'italique�\idx*[ (correction d'italique)]\/\idx*\aftergroup\idx*\it�
% on peut d�finir une macro \itacorr qui effectue automatiquement la correction
\def\itacorr{\it\aftergroup\/}�\idx*\aftergroup�
3) (un {\itacorr cheval})% avec correction d'italique|

\section{Primitive \ttfamily{\textbackslash let}}\label{let}
\idx*[|(]{\let}Pour copier le \idx[!copie]{texte de remplacement} d'une macro vers une autre, on utilise la primitive \verb-\let- qui prend comme arguments deux unit�s lexicales de type \idx{s�quence de contr�le}. Par exemple, �crire \verb-\let\foo=\bar- copiera le texte de remplacement de la macro \verb-\bar- vers \verb-\foo- en �crasant celui de cette derni�re si elle �tait d�j� d�finie. Le signe �=� entre les deux s�quences de contr�le est facultatif et sera souvent omis d�sormais\footnote{En r�alit�, le signe �gal peut aussi �tre suivi d'\emph{un} espace facultatif.}. Une fois cette copie faite, peu importe ce que sera le futur de \verb-\bar-, la copie a lieu � l'instant o� \verb-\let- est rencontr� et si \verb-\bar- est red�finie par la suite, cela n'affectera pas le texte de remplacement de \verb-\foo-.

\showcode/\def\bar{Je suis bar.}
\let\foo\bar % \foo devient �gal � \bar
\def\bar{ABC}% \bar est red�finie
\foo\par% affiche "Je suis bar"
\bar% affiche "ABC"/

Lorsqu'on �crit \verb-\let\foo=\bar-, si \verb-\bar- est une primitive, alors \verb-\foo- devient un \emph{alias} pour cette primitive et pour \TeX{}, elles sont identiques. Il est important de noter que ni \idx\def ni \verb-\let- ne pr�viennent d'aucune fa�on l'utilisateur qu'il �crase une \idx{s�quence de contr�le} et que sa d�finition pr�c�dente sera perdue. Et tant pis si c'est une primitive. Si par malheur on �crit \verb-\let\def\foo-, alors, � partir de ce moment, la primitive \verb-\def- sera �cras�e et il ne sera donc plus possible de d�finir de commande.
\begin{exercice}
\Qu e fait le code suivant : \verb-\let\foo\let\foo\bar\foo- ?
\solution
En proc�dant comme \TeX{} et en ne lisant que ce dont on a besoin, on a d'abord \verb-\let\foo\let- et donc \verb-\foo- devient �gale � la primitive \verb-\let-.

Ensuite, on a \verb-\foo\bar\foo- mais comme \verb-\foo- est devenue un alias de \verb-\let-, tout se passe comme si l'on �crivait \verb-\let\bar\let- et donc, \verb-\bar- devient aussi �gale � \verb-\let-.

Le code rend donc \verb-\foo- et \verb-\bar- �gales � \verb-\let-.
\end{exercice}

La commande \verb-\let- peut aussi �tre utilis�e pour d�finir des �caract�res implicites\idx*{caract�re implicite}�. La syntaxe ne change pas, mais au lieu de la seconde \idx{s�quence de contr�le}, on met un caract�re. Si on �crit par exemple \verb-\let\foo=a-, la \idx{s�quence de contr�le} \verb-\foo- devient un �\texttt a implicite�. Cela signifie qu'elle produira un �\texttt a� � l'affichage et que lorsque \TeX{} teste cette \idx{s�quence de contr�le} (nous verrons comment plus tard), il la voit �gale � �\texttt a�. Il est bien �vident que \verb-\foo- ne peut pas �tre utilis�e � la place de �\texttt a� n'importe o� dans le code. Si on veut �crire \verb-\par-, on ne peut pas �crire \verb-\p\foo r- !

La d�finition d'un caract�re implicite via \verb|\let| ne peut se faire que pour les caract�res \emph{inoffensifs} que l'on peut rencontrer, c'est-�-dire ayant un catcode 11\idx*{catcode!11 (lettre)} ou 12\idx*{catcode!12 (autre)}, ainsi que pour ceux ayant le catcode 1\idx*{catcode!1 (accolade)}, 2, 3, 4, 6, 7, 8. Il est par exemple impossible de d�finir un �\verb|%|� ou un �\verb|\|� implicite avec \verb|\let|. Pour l'espace, cela requiert un plus haut niveau de \TeX nicit� que nous verrons plus loin (page~\pageref{sptoken}).

Pour les \idx[!implicite]{accolade}s ouvrantes et fermantes (dont les catcodes sont respectivement 1\idx*{catcode!1 (accolade)} et 2), il existe des tokens implicites\idx*[!implicite]{token} pr�d�finis tr�s importants qui sont \idx\bgroup et \idx\egroup. Ils sont d�finis par plain-\TeX{} de la fa�on suivante :

\begin{centrage}
\small\verb-\let\bgroup={-\kern2cm\verb-\let\egroup=}-
\end{centrage}

\noindent Ces \emph{\idx[!implicite]{accolade}s implicites} peuvent jouer le m�me r�le de d�limiteur de groupe que les accolades explicites �\verb-{-�\cidx*\{ et �\verb-}-�\cidx*\{ mais dans la grande majorit� des cas, elles ne sont \emph{pas} interchangeables avec les accolades explicites. Par exemple, elles ne peuvent pas �tre utilis�es pour dans la syntaxe de \idx\def pour d�limiter le texte de remplacement d'une macro.
\grandsaut

� ce stade, on peut donc faire un point \TeX nique sur tout ce qui sert � d�limiter un \idx{groupe} � savoir :
\begin{itemize}
       \item la paire \idx\begingroup\linebreak[1]\verb|...|\linebreak[1]\idx\endgroup;
       \item les accolades explicites �\cidx\{� et �\cidx\}� ;
       \item les accolades implicites \idx\bgroup\linebreak[1]\verb|...|\linebreak[1]\idx\egroup.
\end{itemize}

Tout d'abord, un \idx{groupe} ouvert par \idx\begingroup ne peut �tre referm� que par \idx\endgroup et donc, le \idx[!semi-simple]{groupe} semi-simple est totalement ind�pendant du groupe ouvert par des accolades. Les choses sont diff�rentes pour les groupes ouverts et ferm�s par �\cidx\{� et �\cidx\}� ou par �\idx\bgroup� et �\idx\egroup�. Tout d'abord, s'il n'existe aucune contrainte d'�quilibrage d'accolades, �\cidx\{� et \idx\bgroup sont interchangeables pour ouvrir un groupe et �\cidx\}� et \idx\egroup le sont pour le fermer. Enfin, il y a quelques \emph{rares} primitives o� les accolades explicites et implicites sont interchangeables dans leur syntaxe :

\begin{itemize}
       \item les primitives \idx\hbox, \idx\vbox et \idx\vtop attendent apr�s elles un texte entre accolades pour le composer dans une boite (pour en savoir plus, voir la section \ref{boites} page~\pageref{boites} et suivantes).

       Ce sont les seules primitives o� l'on peut indiff�remment utiliser des accolades explicites ou implicites, aussi bien pour ouvrir que pour fermer. Par cons�quent, �\verb|\hbox{a}|� et �\verb|\hbox\bgoup| \verb|a\egroup|� sont �quivalents;
       \item certaines primitives que nous verrons et utiliserons plus loin ont une propri�t� encore plus curieuse\ldots{}

       Ces primitives doivent �tre imm�diatement suivies d'une accolade ouvrante. Les plus connues sont \idx\toks\verb|<nombre>|, \idx\lowercase, \idx\uppercase et pour celles de \idx\eTeX{}, \idx\detokenize et \idx\unexpanded. Elles tol�rent indiff�remment �\verb|{|� ou �\idx\bgroup� pour l'accolade ouvrante. En revanche, l'accolade fermante \emph{doit} �tre une accolade explicite.

       Ainsi, �\idx\lowercase\verb|{Foo}|� et �\idx\lowercase\verb|\bgroup Foo}|� sont accept�s et sont �quivalents.
\end{itemize}

\begin{exercice}
Si l'on �crit le code ci-dessous, va-t-on obtenir �$a^3=b_5$� ?

\centrecode|\let\swichmath=$ \let\expo= ^ \let\ind _ \let\egal= =
\swichmath a\expo3\egal b\ind5$|

\solution
Oui car tous les tokens implicites\idx*[!implicite]{token} d�finis ici le sont avec la bonne syntaxe (le signe \verb-=- et l'espace facultatif qui le suit sont pr�sents ou pas) et surtout, les catcodes des tokens implicites permettent une telle d�finition.
\end{exercice}

\begin{exercice}
\Qu e va t-il se passer si l'on d�finit la macro \verb-\foo- ainsi : \verb-\let\foo={hello}-
\solution
\TeX{} va d'abord lire \verb-\let\foo={- et donc, \verb-\foo- va devenir une accolade implicite.

Ensuite, le reste du code � lire est �\verb-hello}-�. Tout va bien se passer jusqu'� l'accolade fermante. La premi�re accolade ouvrante ayant �t� lue et absorb�e par le \verb-\let-, celle-ci n'a pas �t� prise en compte dans le comptage interne � \TeX{} concernant l'�quilibrage des accolades, l'accolade fermante devient orpheline et \TeX{} va nous gratifier d'un �\verb-Too many }'s-�. Cette derni�re erreur ne surviendra pas si auparavant, une accolade $x$ a �t� ouverte sans encore �tre ferm�e par une accolade fermante; dans ce cas, l'accolade qui suit �\verb|hello| �quilibrera l'accolade $x$ ouverte pr�alablement � ce code.

Pour \emph{d�finir} une macro et lui donner un texte de remplacement, on ne doit utiliser que \idx\def puis le nom de la macro puis le texte de remplacement entre accolades.
\end{exercice}

La primitive \verb-\let- est parfois utile pour faire une sauvegarde d'une commande de fa�on � pouvoir la restaurer � son �tat initial apr�s y avoir apport� des modifications. Prenons un mauvais exemple et d�cidons de modifier la macro \verb-\TeX- pour qu'elle n'affiche plus �\TeX� mais �tEx�. Nous allons d'abord d�finir avec \verb-\let- un alias de \verb-\TeX- que nous appelons \verb-\TeXsauve- puis nous pourrons modifier la commande \verb-\TeX- et utiliser cette commande avec sa nouvelle d�finition. � la fin, avec \verb-\let- � nouveau, nous la restaurerons pour revenir au comportement initial :

\showcode/Initialement, c'est \TeX.\par
\let\TeXsauve\TeX% sauvegarde
\def\TeX{tEx}% red�finition
Ici, on a modifi� \TeX.\par
\let\TeX\TeXsauve% retauration
De nouveau, c'est \TeX./\idx*[|)]{\let}

\section{Les primitives \texttt{\textbackslash csname} et \texttt{\textbackslash endcsname}}\idx*[|(]\csname\idx*[|(]\endcsname
Pour �crire une \idx{s�quence de contr�le}, on peut bien s�r faire pr�c�der son nom du caract�re �\verb|\|�, c'est que nous avons fait jusqu'ici\ldots{} Mais il y a une autre m�thode pour cr�er une \idx{s�quence de contr�le}. On peut utiliser la paire de primitives \verb-\csname- et \verb-\endcsname- qui utilisent les caract�res qui se trouvent entre elles pour les convertir en \idx{s�quence de contr�le}. Par exemple, si \TeX{} rencontre \verb-\csname-\linebreak[1]\verb*- foo-\linebreak[1]\verb-\endcsname-\footnote{L'espace qui suit \texttt{\string\csname} est ignor� en vertu de la r�gle vue � la page~\pageref{regle.espace}}, dans un premier temps il construira l'unit� lexicale �\verb|\foo|� et dans un deuxi�me temps, il lui substituera son texte de remplacement, tout ceci �tant effectu� dans la m�moire de \TeX{}, dans la \idx{pile d'entr�e}. � l'affichage, l'effet est le m�me que si l'on avait directement �crit \verb-\foo-, mais dans les entrailles de \TeX{}, il y a une �tape de plus, celle de former la \idx{s�quence de contr�le} avec ce qui se trouve entre \verb-\csname- et \verb-\endcsname-. L'avantage de cette m�thode est que l'on peut utiliser des caract�res normalement interdits dans le nom de commandes, c'est-�-dire des tokens dont le catcode est diff�rent de 11, celui des lettres. On peut donc construire des s�quences de contr�le dont le nom comporte des espaces, des chiffres, des signes d'op�rations, de ponctuation ainsi que d'autres caract�res r�serv�s dont les codes de cat�gorie sont sp�ciaux (\verb|&|, \verb|#|, \verb|^|, \verb|_|, \verb|$|).

Un autre avantage non n�gligeable est que si jamais la \idx{s�quence de contr�le} form�e par \verb-\csname-\ldots\verb-\endcsname- n'est pas d�finie, \TeX{} la rend �gale � \idx\relax qui est une primitive dont l'action est de ne rien faire. Ainsi, �crire \verb-\foobar- dans le code alors que cette macro n'a pas �t� d�finie par \idx\def ou \idx\let provoquera une erreur de compilation �\texttt{Undefined control sequence}�. En revanche, �crire \verb-\csname foobar\endcsname- revient � invoquer la primitive \idx\relax et il ne se passera donc rien.

Le revers de la m�daille est que, pour \TeX{}, former une \idx{s�quence de contr�le} avec \verb-\csname-\ldots\verb-\endcsname- est \emph{beaucoup} plus lent que de l'�crire directement avec le caract�re d'�chappement. Si c'est possible, il vaut donc mieux �viter d'utiliser cette m�thode dans les boucles des programmes.

\begin{exercice}
Apr�s avoir d�fini la macro \verb-\foo- avec \verb-\def\foo{Bonjour}-, pourquoi rien ne s'affiche lorsqu'on �crit �\verb-\csname foo \endcsname-�?
\solution
Parce que l'espace qui suit le �foo� est pris en compte pour construire le nom de la \idx{s�quence de contr�le}. Ainsi, �crire \verb-\csname-\linebreak[1]\verb*- foo -\linebreak[1]\verb-\endcsname- construit la commande {\fboxsep0.3pt\fbox{\ttfamily\textbackslash foo\textvisiblespace}} qu'il serait fastidieux de construire autrement. Celle-ci �tant ind�finie, la construire avec  \verb-\csname-\ldots\verb-\endcsname- la rend �gale � \idx\relax et il ne se passe donc rien.
\end{exercice}
\begin{exercice}
\label{non.dev.csname}Pourquoi �crire \idx\let\verb-\salut\csname foo\endcsname- pour rendre �gale \verb|\salut| � \verb|\foo| provoque une erreur de compilation ?
\solution
L'erreur survient parce que \TeX{} lit le code de gauche � droite en prenant en compte uniquement ce dont il a besoin. Il lit donc d'abord \idx\let\verb-\salut\csname-. Ce faisant, il rend donc la commande \verb-\salut- �gale � \verb-\csname-. Ayant effectu� cette op�ration, il poursuit avec la suite du code qui est \verb-foo\endcsname-. Les lettres �foo� ne vont pas lui poser de probl�me, il les affichera normalement, mais il va rencontrer la commande \verb-\endcsname- sans avoir rencontr� le \verb-\csname- qui initiait le d�but de la construction du nom de la commande. Il va donc �mettre le message d'erreur �\texttt{Extra \string\endcsname}�.

Pour faire ce que nous voulions, il faudrait forcer \TeX{} � construire la \idx{s�quence de contr�le} \verb|\foo| � partir de \verb*-\csname -\linebreak[1]\verb- foo-\linebreak[1]\verb-\endcsname- avant qu'il ne passe la main � \verb-\let-. Pour provoquer cette action, il faudrait sauter les deux tokens \verb-\let\salut- pour provoquer cette action et revenir o� l'on �tait avant les sauts pour reprendre la lecture du code dans l'ordre normal. Pour effectuer cette man\-\oe uvre non lin�aire qui d�roge � la r�gle de lecture du code, il faut avoir recours � la primitive \idx\expandafter que nous verrons plus loin.
\end{exercice}
\begin{exercice}
On a vu comment d�finir une commande avec \idx\def. Existe-t-il un moyen d'annuler une d�finition et faire qu'une commande pr�alablement d�finie redevienne ind�finie ?
\solution
Il n'existe pas de primitive \verb-\undef- qui rendrait une commande ind�finie \emph{et} l'enl�verait de la table de hashage\footnote{Il s'agit d'une structure interne � \TeX{} o� sont stock�s les appariements entre les noms des macros et l'endroit de la m�moire o� sont stock�s leurs textes de remplacement.}.

On peut cependant combler ce manque. En effet, si l'on d�finit une commande � l'int�rieur d'un \idx{groupe} simple ou semi-simple, la d�finition est locale au groupe et est perdue � sa fermeture. Par cons�quent, si la commande �tait ind�finie avant l'ouverture du groupe, elle le redevient apr�s sa fermeture.

Si l'on souhaite d�finir une commande de fa�on globale, la primitive \idx\global, lorsqu'elle est plac�e devant une assignation, rend cette assignation globale c'est-�-dire qu'elle survit � la fermeture du groupe. La primitive \idx\gdef se comporte comme \idx\global\verb|\def|.
\end{exercice}\idx*[|)]\csname\idx*[|)]\endcsname

\section{Caract�re de contr�le}\idx*[|(]{caract�re de contr�le}

\begin{regle}
Lorsque le caract�re d'�chappement �\cidx\\� est suivi d'un caract�re dont le catcode n'est pas 11\idx*{catcode!11 (lettre)}, celui des lettres, seul ce caract�re est pris en compte et \TeX{} forme ce que l'on appelle un �caract�re de contr�le�.
\end{regle}

Pour former un caract�re de contr�le, on peut donc utiliser des caract�res de catcode 12\idx*{catcode!12 (autre)} comme par exemple �\verb|\.|�, �\verb|\*|�, �\verb|\5|� ou �\verb|\@|�. Il devient surtout possible d'employer des caract�res dont le catcode est plus sensible comme �\verb|\\|�, �\verb|\{|�, �\verb|\}|�, �\verb|\^|�, �\verb|\_|�, �\verb|\&|�, �\verb|\~|�, �\verb|\%|�. Ces derniers, � l'exception de \verb|\\|\footnote{La macro \texttt{\string\\} est d�finie par plain-\TeX{} car elle est utilis�e comme macro auxiliaire pour d�finir une autre macro et la d�finition qui lui est donn�e � cette occasion est laiss�e en l'�tat. Toujours est-il qu'elle n'affiche pas �\texttt{\textbackslash}�, qui s'obtient avec �\texttt{\textbackslash char\number`\\}� ou mieux avec �\texttt{\textbackslash char`\textbackslash\textbackslash}�.

Du c�t� de \LaTeX{}, la macro \texttt{\string\\} est d�finie pour commander d'aller � la ligne pendant le paragraphe en cours et est red�finie dans plusieurs environnements (centering, raggedright, raggedleft, eqnarray, tabbing, array, tabular).}, sont d�finis par plain-\TeX{} pour afficher le caract�re qui forme leur nom, caract�re qu'il serait plus difficile d'afficher sinon. Pour cela, la primitive \idx\chardef est employ�e avec cette syntaxe :

\centrecode-\chardef\<macro>=<code de caract�re>-

\noindent Si l'on s'int�resse au code des macros du format plain-\TeX{} qui est contenu dans le fichier �\verb|plain.tex|�\idx*{fichier!plain.tex}, on d�couvre par exemple � la ligne \no 651 que le caract�re de contr�le \idx\& est d�fini par

\centrecode-\chardef\&=`\&-

\noindent ce qui a pour effet de rendre �quivalent (� la mani�re de \idx\let) le caract�re de contr�le \verb|\&| � �\idx\char\verb|`\&|�.

\begin{regle}
Contrairement aux s�quences de contr�le dont le nom est form� de lettres, les \idx{espace}s qui suivent les � caract�res de contr�le � ne sont pas ignor�s. La seule exception est la primitive \idx\ , qui ajoute un espace � la liste courante. En effet, si cette derni�re est suivie d'un espace, alors deux \idx[!cons�cutifs]{espace}s se suivent dans le code et une autre r�gle stipule que le second est ignor�.
\end{regle}

\begin{exercice}
En ayant fait les d�finitions �\verb*-\def\9{\ \:}-� et �\verb*-\def\:{ \  X}-�, quel affichage obtiendra-t-on avec �\verb*-a\9 fin-� ?
\solution
On obtient la lettre �a� suivie du texte de remplacement de \verb-\9-. Celui-ci commence par \verb*-\ - (espace qui sera affich�) suivi de \verb-\:-. Le texte de remplacement de \verb|\:| commence par : \verb*- - (espace qui sera affich�) puis \verb*-\  - (le deuxi�me espace est ignor�) suivi d'un �\verb|X|�. Et enfin, l'espace apr�s \verb*-\9 - sera affich� avant le mot �fin�. On obtient donc �a\verb*-   -X\verb*- -fin�.
\end{exercice}

\begin{exercice}
\Qu elle diff�rence y t-il entre �\verb-\+-� et �\idx\csname\verb|+|\idx\endcsname�
?
\solution
Il n'y a pas de diff�rence � l'affichage sauf si le caract�re qui suit dans le code est un espace. Il sera comptabilis� avec \verb-\+- et ignor� avec \idx\csname\verb|+|\idx\endcsname car l'espace qui suit la \idx{s�quence de contr�le} \idx\endcsname est ignor�.

De plus, si le caract�re de contr�le \verb-\+- n'a pas �t� d�fini, �crire \verb-\+- provoque une erreur � la compilation de type �\texttt{Undefined control sequence}�. Au contraire, avec \idx\csname\verb|+|\idx\endcsname, il n'y aurait pas d'erreur car lorsque \idx\csname construit une \idx{s�quence de contr�le} non d�finie, elle la rend �gale � \idx\relax, et ici, tout se passerait comme si on avait �crit \idx\let\verb|\+=|\idx\relax.
\end{exercice}
\begin{exercice}
\Qu elle diff�rence y a-t-il entre �\idx\def\verb-\foo{A}-� et �\idx\let\verb-\foo=A-� ?
\solution
� l'affichage, dans les deux cas, \verb-\foo- produit un �A�. Par contre, en interne, les choses sont diff�rentes\ldots

Lorsque \verb-\foo- est d�finie avec \idx\def, \TeX{} la \emph{remplace} par un �A�.

Lorsque \verb-\foo- est d�finie avec \idx\let, aucun remplacement n'est fait puisque \verb-\foo- \emph{est} un �A� et n'a aucun texte de remplacement.
\end{exercice}

Le fait que les commandes caract�res prennent en compte les espaces qui les suivent permet de d�finir un espace implicite �\sptoken de cette fa�on\footnote{C'est ainsi que \texttt{\string\@sptoken} est d�fini dans le code du noyau \LaTeX.} :\label{sptoken}

\centrecodespc/\def\:{\let\sptoken= }��*\sptoken�
\: /

\noindent Toute l'astuce r�side dans le fait que l'espace qui suit \verb|\:| � la 2\ieme{} ligne est pris en compte. La man\-\oe uvre m�rite une petite explication. La premi�re ligne d�finit un texte de remplacement pour la macro \verb|\:|. � la deuxi�me ligne, \TeX{} va remplacer \verb|\:| par son texte de remplacement ce qui va donner :

\begin{centrage}
\small\boxtoken{\let\string\sptoken= }\verb*| |%
\end{centrage}

Pour plus de clart�, le texte de remplacement de \verb|\:| est encadr�. Dans ce texte de remplacement, l'espace qui suit le signe \verb|=| est l'espace facultatif qui est permis avec la primitive \idx\let. Cet espace, faisant partie de la syntaxe de \idx\let, est ignor� et donc, \idx\let rend �\sptoken �gal au token suivant qui est �\verb*| |�, l'espace qui suit le caract�re de contr�le \verb|\:|.

Dans le code ci-dessus, le second espace n'est pas ignor� car les deux espaces ne sont pas cons�cutifs dans le code source. Ils sont cons�cutifs apr�s que \TeX{} ait remplac� \verb|\:| par son texte de remplacement. La r�gle de la page~\pageref{regle.espace} ne s'applique donc pas.

\begin{exercice}
Comment serait d�fini �\sptoken si l'on �crivait na�vement \idx\let\verb*-\sptoken=  - ?
\solution
Comme on l'a vu, le premier espace, facultatif, fait partie de la syntaxe de \idx\let et ne peut donc pas servir � d�finir �\sptoken. Le second est ignor� puisque la r�gle veut que deux espaces cons�cutifs dans le code n'en forment qu'un.

Dans ce cas, �\sptoken sera un alias pour le token qui \emph{suivra dans le code} et que l'on n'a pas pr�cis� dans l'�nonc� de l'exercice. Il faut noter que si ce qui suit est un saut de ligne, �\sptoken sera un alias de la commande \idx\par car deux sauts de lignes cons�cutifs sont �quivalents � la commande \idx\par :

\showcode/\let\sptoken=  %2 espaces avant le "%"��*\sptoken�

La commande \sptoken compose le paragraphe/
\end{exercice}\idx*[|)]{caract�re de contr�le}

\section{Caract�res actifs}\idx*[|(]{caract�re actif}
Un caract�re est dit \emph{actif} lorsqu'il rev�t les m�mes propri�t�s qu'une commande : on peut le d�finir avec \idx\def et, lorsqu'il est rencontr� par \TeX{}, son texte de remplacement lui est substitu�. En contrepartie, il ne fait plus partie de la cat�gorie de lettres et n'est donc pas autoris� dans les noms des s�quences de contr�le.

\begin{regle}
Un caract�re est \emph{actif} lorsque son code de cat�gorie vaut 13\idx*[!13 (actif)]\catcode. Dans ce cas, on peut lui donner un texte de remplacement comme on le fait pour une macro.
\end{regle}

Par d�faut, aussi bien avec plain-\TeX{} qu'avec \LaTeX, seul le caract�re �\cidx\~� est actif fait les choses suivantes :
\begin{enumerate}
       \item interdire une coupure en sp�cifiant une haute \idx{p�nalit�} (avec la primitive \idx\penalty suivie d'un entier �lev�, par exemple \numprint{1000});
       \item appeler la primitive \idx\ qui affiche une espace.
\end{enumerate}
Ainsi, plain-\TeX{} dit :

\centrecode-\def~{\penalty1000 \ }-

\noindent La forte \idx{p�nalit�} de \texttt{1000} interdit toute coupure et le tout forme donc une � \idx[!ins�cable]{espace} ins�cable �, o� l'adjectif \emph{ins�cable} exprime que cette espace ne pourra donner lieu � une coupure de ligne.
\grandsaut

� notre tour, supposons que l'on souhaite rendre le caract�re �\verb|W|� actif. Nous le ferons � l'int�rieur d'un groupe, car il est prudent de limiter la port�e des modifications des codes de cat�gorie.

Nous savons que \idx\catcode\verb-`\<car>=<nombre>- modifie le catcode d'un caract�re, o� \verb-<nombre>- est un nombre de 0 � 15\footnote{Le caract�re �\texttt`� est l'apostrophe \emph{inverse} et s'obtient parfois en tapant la combinaison de touches \bioLegacyKeyGlyph{A_l_t_G_r}+\bioLegacyKeyGlyph{seven}. Pour exprimer le nombre �gal au code de cat�gorie d'un caract�re, on peut �crire \verb|\`<car>| ou \verb|`<car>|. La seconde �criture est cependant moins recommandable puisque l'on s'expose � des erreurs lorsque \verb|<car>| a un catcode sp�cial (0 ou \number\catcode`\%).}. Ici, on va donc �crire \verb-\catcode`\W=13-. Et ensuite, il suffit de d�finir le texte de remplacement du caract�re actif \verb|W|, par exemple �wagons� :

\showcode/{% d�but du groupe
\catcode`\W=13 \def W{wagons}�\idx*\catcode�
Les W constituent le train.
}% fin du groupe/

Voici la r�gle corroborant ce que l'on constate dans l'exemple ci-dessus :

\begin{regle}
Un \idx{espace} apr�s un caract�re actif est pris en compte.
\end{regle}

Il est plus difficile est de cr�er une commande qui rende le caract�re \verb|W| actif. Appelons \verb-\actiw- cette commande et donnons-nous le cahier des charges suivant : elle devra rendre le caract�re \verb|W| actif et lui donner le texte de remplacement �wagons�. Nous placerons un \idx\begingroup avant d'appeler cette macro et un \idx\endgroup � la fin du texte o� l'on souhaite que le caract�re \verb|W| soit actif.

Pour d�finir cette commande \verb-\actiw-, on ne peut pas �crire directement ceci :

\centrecode-\def\actiw{\catcode`\W=13 \def W{wagons}}-

\noindent En effet, lorsque \TeX{} remplace \verb|\actiw| par son texte de remplacement, \emph{tous} les tokens dans ce texte de remplacement ont leurs catcodes fig�s depuis que la d�finition a �t� faite. Et donc, le �\verb|W|� qui suit le \verb|\def| a un catcode de 11.

Par cons�quent, lorsque ce texte de remplacement sera ex�cut�, \TeX{} va trouver \verb-\def W{wagons}- o� \verb|W| est une lettre (de catcode 11\idx*{catcode!11 (lettre)}), et il va se plaindre de ne pas trouver une \idx{s�quence de contr�le} apr�s le \idx\def en affichant le message d'erreur �\texttt{Missing control sequence}�.

Il faut comprendre que l'ordre �\verb|\catcode`\W=13|� qui est dans texte de remplacement ne peut pas agir sur les �\verb|W|� de ce texte de remplacement puisque leurs catcodes sont fig�s, mais agira sur le code qui reste � lire \emph{apr�s} \verb|\actiw|.

Pour sortir de ce mauvais pas, il faut rendre \verb|W| actif \emph{avant} que \TeX{} ne lise le texte de remplacement de \verb-\wagon-. Pour limiter la port�e de cette op�ration, on va donc le faire dans un groupe et utiliser \idx\gdef, pour que la d�finition soit globale et survive � la fermeture du groupe. Voici la fa�on correcte de d�finir \verb-\actiw- :

\showcode/\begingroup \catcode`\W=13 �\idx*\begingroup\idx*\endgroup�
\gdef\actiw{%�\idx*\gdef�
       \catcode`\W=13 �\idx*\catcode�
       \def W{wagons}}
\endgroup
a) Les trains ne sont pas constitu�s de W !\par
b) \begingroup\actiw Ici, les W forment les trains.\endgroup\par
c) Ici, les W sont redevenus des lettres./

\begin{exercice}
D�finir deux s�quences de contr�le \verb-\>- et \verb-\<- telles qu'entre elles, les mots soient espac�s de \numprint[mm]5. Le comportement normal doit �tre r�tabli ensuite.

On utilisera la primitive \idx\hskip suivie d'une dimension pour ordonner � \TeX{} d'ins�rer une espace horizontale de la valeur de la dimension.
\solution
Comme on l'a vu, on ne peut pas �crire directement ce code comme ci-dessous pour d�finir la macro \verb-\>- :

\centrecode-\def\>{\begingroup\catcode`\ =13 \def {\hspace{5mm}}}-

\noindent puisqu'au moment o� cette ligne est lue par \TeX{}, l'espace a son code de cat�gorie naturel de 10. Celui-ci ne pourra plus �tre chang� par la suite.

Voici la bonne fa�on de proc�der : il suffit de rendre la commande \verb-\<- �gale � \idx\endgroup ce qui cl�turera le processus initi� par \verb-\>- qui avait ouvert le groupe semi-simple :

\showcode/\begingroup�\idx*\begingroup�
       \catcode`\ =13 % rend l'espace actif�\idx*\catcode�
       \gdef\>{\begingroup�\idx*\gdef�
               \catcode`\ =13
               \def {\hskip5mm\relax}}�\idx*\hskip\idx*\relax�
\endgroup
\let\<=\endgroup�\idx*\let�
a) Du texte normal\par
b) \>Des mots tr�s espac�s\<\par
c) Du texte normal/
\end{exercice}

La pr�sence d'un \idx\relax apr�s la dimension de \verb|5mm| stoppe la lecture de la dimension. En effet, comme nous le verrons plus loin, une dimension peut avoir des composantes �tirables qui commencent par le mot-cl� �\verb|plus|�. Sans le \idx\relax, si jamais un espace actif �tait suivi du mot �\verb|plus|�, alors \TeX{} penserait que ce mot fait partie int�grante de la dimension et irait chercher encore plus loin la composante �tirable. Le \verb|\relax| agit donc ici comme une s�curit�.
\grandsaut

Une application utile des caract�res actifs est de rendre les signes de ponctuation haute actifs. C'est ce que fait l'extension pour \LaTeX{} �\verb-babel-� charg�e avec l'option �\verb-frenchb-� de Daniel \textsc{Flipo}\idx*{package!babel (frenchb)}. Les signes de ponctuation \emph{haute} �\string!�, �\string?�, �\string:� et �\string;� sont rendus actifs de fa�on � ins�rer une espace fine ins�cable avant eux. Nous allons imiter ce comportement et rendre la virgule active. L'id�e est de la programmer pour qu'elle supprime un �ventuel espace avant elle, affiche le caract�re �\verb|,|�, ins�re une espace justifiante (c'est-�-dire �tirable) et enfin, ne tienne pas compte des espaces qui pourraient suivre. Pour effectuer ces actions, certaines primitives sont n�cessaires :
\begin{itemize}
       \item si ce qui pr�c�de est un espace �tirable, la primitive \idx\unskip le supprime ;
       \item \idx\string transforme le token qui suit en un ou plusieurs tokens dont les codes de cat�gorie sont 12. Cette primitive est utile pour rendre n'importe quel \idx{token} inoffensif et donc imm�diatement affichable. Par exemple, �\verb-\string#-� produit �\string#� de m�me que �\verb-\string\def-� produit �\string\def�. Lorsque la virgule sera active, �\verb-\string,-� affichera une virgule non active;
       \item \idx\ignorespaces demande � \TeX{} d'ignorer tous les espaces qui vont suivre et d'avancer sa t�te de lecture jusqu'au prochain caract�re qui n'est pas un espace.
\end{itemize}

\showcode/\begingroup�\idx*\begingroup�
       \catcode`\,=13 \def,{\unskip\string,\space\ignorespaces}�\idx*\unskip\idx*\string\idx*\space\idx*\ignorespaces\idx*\catcode�
       La rue assourdissante autour de moi hurlait.

       Longue , mince,en grand deuil  ,  douleur majestueuse ,

       Une femme passa   ,d'une main fastueuse

       Soulevant,balan�ant le feston et l'ourlet ;

\endgroup\medbreak\hfill Charles {\sc Baudelaire}�\idx*\endgroup\idx*\medbreak\idx*\hfill\idx*\sc�/

\begin{exercice}
Par d�faut, le caract�re ins�r� par \TeX{} � chaque \idx{fin de ligne} est le retour charriot, qui s'�crit �\verb-^^M-\verbidx*[ (retour charriot)]{^^M}� et qui a comme code de cat�gorie \number\catcode`\^^M. La r�gle de \TeX{} vue page~\pageref{regle.catcode5} veut que \emph{deux} retours charriots cons�cutifs (ou plus g�n�ralement deux tokens cons�cutifs de catcode \number\catcode`\^^M) soient �quivalents � la commande \idx\par\idx*{catcode!5 (retour charriot)}.

Reprendre l'exemple pr�c�dent en faisant en sorte qu'un seul retour charriot suffise � aller � la ligne suivante.
\solution
Il suffit de rendre le caract�re \verb-^^M- actif et le rendre �gal � \idx\par avec un \idx\let :

\showcode/\begingroup�\idx*[|etc]\begingroup\forbidindex\begingroup�
       \catcode`\,=13 \def,{\unskip\string, \ignorespaces}�\idx*\unskip\idx*\string\idx*\ignorespaces\idx*\catcode�
       \catcode`\^^M=13 \let ^^M\par�\idx*\let� % rend le retour charriot �gal � \par
       La rue assourdissante autour de moi hurlait.
       Longue , mince,en grand deuil  , douleur majestueuse ,
       Une femme passa   ,   d'une main fastueuse
       Soulevant,balan�ant le feston et l'ourlet ;
\endgroup\medbreak\hfill Charles {\sc Baudelaire}�\idx*[|etc]\endgroup\forbidindex\endgroup\idx*\medbreak\idx*\hfill\idx*\sc�/
\end{exercice}

\begin{exercice}
Dans un texte � l'int�rieur d'un groupe, inventer un proc�d� qui effectue un remplacement par permutation circulaire des voyelles, c'est-�-dire qui remplace a par e, e par i, i par o, o par u, u par y et y par a.
\solution
\label{permutation.voyelles}La difficult� vient du fait qu'une fois qu'un caract�re est rendu actif, il devient semblable � une \idx{s�quence de contr�le} et on ne peut plus s'en servir pour former le nom d'une \idx{s�quence de contr�le}. C'est donc une m�thode peu recommandable, il en existe d'ailleurs de meilleures. Il n'emp�che qu'en l'�tat actuel de nos connaissances, nous ne pouvons proc�der qu'en touchant aux codes de cat�gorie.

Avant de toucher aux catcodes des voyelles, on va donc d�finir des s�quences de contr�le \verb-\AA-, \verb-\EE-, etc. qui, � l'aide de la commande \idx\let vont devenir des lettres implicites, �a� pour \verb-\AA-, �e� pour \verb-\EE-, etc.

Ensuite, les commandes \idx\catcode et \verb|\let| contenant des voyelles, on ne pourra pas y faire appel apr�s avoir modifi� les codes de cat�gorie. On va donc d�finir avec \verb-\let- des s�quences de contr�le �quivalentes dont les voyelles seront en majuscule. On aura donc \verb-\lEt- pour \verb-\let- et \verb-\cAtcOdE- pour \verb-\catcode-.

On peut ensuite rendre chaque voyelle active et la mettre \verb|let|-�gale � \verb-\AA-, \verb-\EE-, etc. selon la lettre que l'on veut obtenir.

\showcode[\def\`##1{{\accent0 ##1}}\def\'##1{{\accent1 ##1}}]/{% ouvre un groupe
       \let\AA=a \let\EE=e \let\II=i \let\OO=o \let\UU=u \let\YY=y�\idx*\let�
       % sauvegarder avant de modifier le catcode de a et e :
       \let\lEt=\let \let\cAtcOdE=\catcode�\idx*\catcode�
       \cAtcOdE`\a=13 \lEt a=\EE \cAtcOdE`\e=13 \lEt e=\II
       \cAtcOdE`\i=13 \lEt i=\OO \cAtcOdE`\o=13 \lEt o=\UU
       \cAtcOdE`\u=13 \lEt u=\YY \cAtcOdE`\y=13 \lEt y=\AA
       Ce texte devenu \`a peine reconnaissable montre que le r\'esultat
       contient des sonorit\'es catalanes, corses ou grecques assez
       inattendues.
}% ferme le groupe/

Les contorsions n�cessaires pour arriver � nos fins montrent que l'on ne touche pas aux codes de cat�gorie sans se cr�er de r�elles difficult�s et sans prendre de gros risques si l'on contr�le mal la port�e des modifications. Changer un code de cat�gorie de caract�re doit donc rester exceptionnel et rester r�serv� � des buts tr�s sp�cifiques. En effet, des m�thodes plus sures existent, m�me si elles ont aussi d'autres inconv�nients.

Une optimisation du code serait d'utiliser le caract�re d�j� actif �\cidx\~� comme alias de \idx\catcode. Bien s�r, on y perd en lisibilit�\ldots{} On peut aussi profiter de la permutation circulaire pour d�finir chaque voyelle rendue active comme alias de la prochaine voyelle, non encore rendue active. On �conomise ainsi des s�quences de contr�le pour les lettres implicites. On n'en a besoin que d'une seule, \verb-\AA-, lettre implicite pour �a� :

\showcode[\def\`##1{{\accent0 ##1}}\def\'##1{{\accent1 ##1}}]/{%
       \let\AA=a \let\lEt=\let \let~=\catcode�\idx*\catcode\idx*\let\cidx*\~�
       ~`a=13 \lEt a=e ~`e=13 \lEt e=i ~`i=13 \lEt i=o
       ~`o=13 \lEt o=u ~`u=13 \lEt u=y ~`y=13 \lEt y=\AA
       Ce texte devenu \`a peine reconnaissable...
}/
\end{exercice}\idx*[|)]{caract�re actif}

\section{Signification d'une commande}
Il est possible de demander � \TeX{} la � signification � d'une \idx[|etc]{s�quence de contr�le}\forbidindex{s�quence de contr�le}. Pour cela, la primitive \idx\show �crit dans le \idx[!log]{fichier} log le \idx{texte de remplacement} de la macro ou simplement son nom si c'est une primitive. Cette primitive, lorsqu'elle est utilis�e � bon escient dans le code permet un d�bogage efficace par la lecture du \idx[!log]{fichier} \verb|log|. Pour diriger les informations d�livr�es par \idx\show dans le flux de lecture de \TeX{} pour par exemple les afficher dans le document final, il faut utiliser la primitive \idx\meaning.

\showcode/a) \def\foo{Bonjour}\meaning\foo\par�\idx*\meaning�
b) \let\bar=\foo\meaning\bar\par% \foo est "copi�e" vers \bar
c) \def\baz{\foo}\meaning\baz\par
d) \catcode`\W=13 \def W{Wagons}% W est un caract�re actif�\idx*\catcode�
  \meaning W\par
e) \meaning\def% \def est une primitive�\idx*\meaning�/

Il est important d'insister entre la diff�rence qui existe entre \verb|\let\bar\foo| (cas b) et \verb|\def\baz{\foo}| (cas c). Dans le premier cas, \verb|\bar| est rendue �gale � \verb|\foo| et � partir de ce moment, \verb|\bar| a comme texte de remplacement �Bonjour�, ind�pendamment de ce que devient \verb|\foo|. En revanche, lorsqu'on �crit \verb|\def\baz{\foo}|, la macro \verb|\baz| a comme texte de remplacement \verb|\foo| et donc, � chaque fois qu'elle est ex�cut�e, elle d�pend de ce qu'est \verb|\foo| � ce moment-l�.

\begin{exercice}
Mettre en �vidence � l'aide de la primitive \idx\meaning que 2 retours charriots\verbidx*[ (retour charriot)]{^^M} cons�cutifs sont interpr�t�s par \TeX{} comme �tant la primitive \verb-\par-.
\solution
Il suffit de d�finir une commande dont le texte de remplacement est constitu� de 2 retours charriots cons�cutifs et de faire afficher � \TeX{} la signification de cette commande, voire faire suivre \verb|\meaning| de deux retours � la ligne :

\showcode/a) \def\foo{

}Signification de \string\foo{} : \meaning\foo�\idx*\string\idx*\meaning�

b) Signification de deux retours charriots cons�cutifs : \meaning
/
\end{exercice}

\begin{regle}
La primitive \idx\show �crit dans le \idx[!log]{fichier} \verb|log| la � signification � du token\idx*[!signification]{token} qui la suit :
       \begin{enumerate}
               \item si ce token est une macro (ou un caract�re actif), le texte �\texttt{macro->}� suivi du \idx{texte de remplacement} de cette macro est �crit;
               \item si ce token est une primitive, qui par d�finition n'a pas de \idx{texte de remplacement}, le nom de la primitive est �crit;
               \item sinon, \TeX{} �crit un texte bref (caract�risant le catcode du token) suivi du token.
       \end{enumerate}
La primitive \idx\meaning �crit les m�mes choses que \idx\show sauf qu'elle les �crits dans le flux de lecture de \TeX{}, dans la \idx{pile d'entr�e}.
\end{regle}

Voici ce que provoque \verb|\meaning| pour les tokens de chaque cat�gorie qu'il est possible de mettre apr�s \verb|\meaning| :
\begingroup
\def~{\penalty\@M \ }
\showcode/a) \meaning\relax\par% primitive�\idx*\meaning�
b) \meaning {\par% catcode 1
c) \meaning }\par% catcode 2
d) \meaning $\par% catcode 3
e) \meaning &\par% catcode 4
g) \meaning #\par% catcode 6
h) \meaning ^\par% catcode 7�\idx*{catcode!7\space(exposant)}�
i) \meaning _\par% catcode 8
j) \meaning a\par% catcode 11 (une lettre)�\idx*{catcode!11\space(lettre)}�
k) \meaning +\par% catcode 12 (caract�re "autre")�\idx*{catcode!12\space(autre)}�
l) \meaning ~\par% catcode 13 (caract�re actif)�\idx*{catcode!13\space(actif)}�/%
\endgroup\iffalse$\fi

\begin{exercice}
On ne peut pas afficher la signification d'un espace (catcode 10\idx*{catcode!10 (espace)}) puisqu'�crire �\idx\meaning\verb*| |� ferait que l'espace qui suit la primitive serait ignor� et \idx\meaning prendrait le token d'apr�s. Comment s'y prendre pour afficher la signification d'un espace avec \idx\meaning ?
\solution
On peut employer la m�me astuce qu'avec �\sptoken de la page~\pageref{sptoken}. On s'y prend
ici avec \idx\let, en enfermant le tout dans un groupe semi-simple :

\showcode/\begingroup% dans un groupe�\idx*\begingroup�
       \let\*=\meaning% rendre \* �gal � \meaning�\idx*\meaning�
       \* %<- espace pris en compte
\endgroup% fermer le groupe�\idx*\endgroup�/

En revanche, on ne peut pas �crire apr�s \idx\meaning les caract�res de catcode suivants :
\begin{itemize}
       \item 0 car le caract�re d'�chappement s'apparie toujours avec autre chose pour former une \idx{s�quence de contr�le}. Un token de catcode 0\idx*{catcode!0 (caract�re d'�chappement)} ne peut exister comme entit� seule;
       \item 5 car ce caract�re est vu comme un espace;
       \item 9 car c'est le num�ro de la cat�gorie des caract�res �ignor�s� et le token serait aussi ignor�, m�me apr�s \idx\meaning;
       \item 14 car un caract�re de commentaire est ignor� ainsi que tout ce qui va jusqu'� la fin de la ligne;
       \item 15 car un caract�re � invalide � n'est pas permis et provoque une erreur de compilation lorsqu'il est vu par \TeX{}.
\end{itemize}
\end{exercice}

\section{Le caract�re d'�chappement}\idx*[|(]{caract�re d'�chappement}
Par d�faut, le caract�re d'�chappement est �\cidx\\�, c'est � ce caract�re que \TeX{} reconnait le d�but d'une \idx{s�quence de contr�le}. Comme presque tout dans \TeX{}, ce caract�re est modifiable. En effet, tout caract�re de catcode 0\idx*{catcode!0 (caract�re d'�chappement)} est, par d�finition, un caract�re d'�chappement. Supposons qu'� l'int�rieur d'un groupe semi-simple, on donne � �\verb-*-� le code de cat�gorie 0 et � �\verb-\-� le code de cat�gorie 12 qui est celui des caract�res �autres�. Ayant fait ces modifications, nous devrons mettre �\verb-*-� devant les s�quences de contr�le et pourrons alors afficher �\verb-\-� directement puisqu'il sera devenu un caract�re inoffensif :

\showcode/\begingroup�\idx*\begingroup�
\catcode`\*0 �\idx*\catcode�
\catcode`\\12 % \ n'est plus un caract�re d'�chappement
*def*foo{bar}
*LaTeX{} et la macro *string*foo : *foo.

L'ancien caract�re d'�chappement  "\" et \TeX.
*endgroup/

\begin{exercice}
Concernant l'exemple pr�c�dent :
\begin{enumerate}
       \item Aurait-on pu �crire � la ligne 3 ceci : �\verb-*catcode`*\12-�\idx*\catcode ?
       \item Si l'on avait utilis� \idx*\gdef\verb-*gdef- pour que la macro \verb-*foo- survive � la fermeture du groupe, aurait-on pu l'appeler par la suite avec \verb-\foo- ?
\end{enumerate}
\solution
\begin{enumerate}
       \item Apr�s la ligne \no2, il y a 2 caract�res d'�chappement qui sont �\verb-\-� et �\verb-*-�. Tant qu'ils ont ce pouvoir, ils sont interchangeables. La r�ponse est donc oui.

       En revanche, la ligne 2 fait perdre ce pouvoir au caract�re �\verb-\-� ce qui fait qu'ensuite, seul �\verb-*-� peut �tre utilis� comme caract�re d'�chappement jusqu'� ce que le groupe soit ferm� par \verb-*endgroup-\idx*\endgroup.
       \item N'importe quel caract�re ayant le catcode 0\idx*{catcode!0 (caract�re d'�chappement)} peut �tre utilis� pour amorcer le nom d'une macro. En temps normal, seul �\verb-\-� est disponible donc la r�ponse est oui.
\end{enumerate}
\end{exercice}

On peut observer que \idx\string, qui convertit le nom d'une \idx{s�quence de contr�le} en caract�res de catcode 12\idx*{catcode!12 (autre)}, ne tient pas compte de la modification du caract�re d'�chappement puisque l'on obtient \verb-\foo- et non pas \verb-*foo-. Cela dit, ce comportement est un peu normal car s'il y avait plusieurs caract�res d'�chappement, \TeX{} serait bien ennuy� pour en choisir un. Pour sch�matiser, on peut consid�rer que le choix d'un caract�re d'�chappement par son catcode concerne un m�canisme d'\emph{entr�e} pour \TeX{} puisqu'il s'agit d'une r�gle concernant la lecture du code tap� par l'utilisateur. La primitive \idx\string appliqu�e aux macros, au contraire, concerne un m�canisme de sortie puisqu'elle provoque la conversion d'une donn�e interne de \TeX{} (le nom de la macro) en caract�res imm�diatement affichables. Ces deux m�canismes se repr�sentent le caract�re d'�chappement par des moyens ind�pendants. Pour \idx\string, il faut le d�finir via la primitive \idx\escapechar qui attend apr�s elle le code de caract�re du caract�re d'�chappement que l'on souhaite. Dans l'exemple pr�c�dent pour que le caract�re d'�chappement affich� par \idx\string soit �\verb-@-�, il suffit de rajouter juste apr�s le \idx\begingroup :

\begin{centrage}
        \small\verb|\espcapechar=64 |\qquad ou bien\qquad \verb|\escapechar=`\@|
\end{centrage}

Notons que tout comme \idx\string, les primitives \idx\meaning et \idx\show tiennent compte de la modification du \idx\escapechar. Enfin, si l'on assigne � \idx\escapechar un code inf�rieur � 0 ou sup�rieur � 255, alors aucun caract�re d'�chappement ne pr�c�dera le nom de la macro.

\showcode/\def\foo{\bar}
\begingroup�\idx*\begingroup�
a) \escapechar=-1  \meaning\foo\qquad% pas de caract�re d'�chappement�\idx*\escapechar\idx*\meaning\idx*\qquad�
b) \escapechar=`\@ \meaning\foo\qquad% "@" est le caract�re d'�chappement
\endgroup�\idx*\endgroup�
c) \meaning\foo% caract�re d'�chappement par d�faut/

\begin{exercice}\label{construction.nom.etrange}
D�finir une commande dont le nom est \verb-\-\boxtoken{1\string\2\string\a} et dont le texte de remplacement est �foo� et v�rifier en appelant cette commande que la d�finition est bien correcte.
\solution
Il va falloir agir dans un groupe, modifier les catcodes de 1, 2 et \cidx\\ pour les mettre � 11, cat�gorie des lettres, seules autoris�es dans les noms de macros. Comme �\cidx\\� est le caract�re d'�chappement, il va aussi falloir en d�finir un autre, choisissons �\verb-|-�. Comme toutes ces man\-\oe uvres ont lieu dans un groupe, nous utiliserons \verb-|gdef-\idx*\gdef pour que la d�finition de la macro survive � la fermeture du groupe.

Le probl�me ici est que l'on doit donner \emph{en dernier} � �\verb|1|� le catcode 11. En effet, si on le faisait avant, �\verb|1|� deviendrait pour \TeX{} une \emph{lettre} et lorsqu'il rencontrerait \verb-|catcode`|2=11-, le �\verb|11|� serait, � ses yeux, deux lettres qui ne peuvent former un nombre, car les tokens qui forment les nombres doivent avoir un catcode de 12\idx*{nombre!catcode des chiffres} ! Nous aurions droit � une erreur de compilation du type �\texttt{Missing number}�.

Enfin, pour appeler la macro � l'ext�rieur du groupe, on doit utiliser la paire \idx\csname...\linebreak[1]\idx\endcsname dans laquelle on prendra soin de transformer le caract�re d'�chappement \verb-\- en un caract�re inoffensif de catcode 12\idx*{catcode!12 (autre)} avec la primitive \idx\string.

\showcode/\begingroup
       \catcode`\|=0 |catcode`|\=11 |catcode`|2=11 |catcode`|1=11 �\idx*\catcode\forbidindex\catcode�
       |gdef|1\2\a{foo}�\idx*\gdef�
|endgroup�\idx*\endgroup�
Voici la macro : \csname 1\string\2\string\a\endcsname�\idx*\string\idx*\csname\idx*\endcsname�/

Dans ce cas, ces manipulations de catcode, assez dangereuses et plut�t chatouilleuses, sont fort heureusement inutiles avec la primitive \idx\expandafter que nous verrons plus loin. Il s'agit d'un exemple purement p�dagogique\ldots
\end{exercice}\idx*[|)]{caract�re d'�chappement}

\section{Une autre fa�on de stocker des tokens}
Arriv�s � ce point, nous savons qu'une macro peut servir � stocker des tokens. Ces tokens sont plac�s dans le texte de remplacement de la macro lors de sa d�finition avec \verb|\def|. Bien qu'on les utilise aussi dans ce but, les possibilit�s d'une macro ne se limitent pas � ce simple stockage et c'est ce que nous allons d�couvrir dans les chapitres suivants.

Si l'on recherche uniquement le c�t� � stockage de tokens �, \TeX{} propose un autre type de structure : les registres de tokens\idx*[|(]{registre!token}\idx*[|(]{token!registre}. Ce sont de zones de m�moire (au nombre de 256 pour \TeX{} et \numprint{32768} pour \idx\eTeX) auxquelles on acc�de � l'aide de la primitive \idx\toks suivie du num�ro de registre. Ainsi, \verb|\toks17| fait r�f�rence au registre de token \no17. Il est admis que le registre \no0 sert de registre brouillon et peut �tre utilis� sans trop de risque n'importe o�.

\TeX{} met aussi � disposition la primitive \idx\toksdef et par exemple, �crire

\centrecode-\toksdef\foo=17-\idx*\toks

\noindent rend \verb|\foo| �quivalent � \verb|\toks17| de telle sorte que le registre \no17 peut �tre d�sign� par la \idx{s�quence de contr�le} \verb|\foo|. L'�quivalence dont il est question ici ressemble � celle de \idx\let en ce sens que \verb|\foo| n'aura pas de texte de remplacement, mais \emph{sera} \verb|\toks17|.

Il est d�conseill� d'utiliser un num�ro non nul arbitrairement et sans pr�caution, car il se pourrait que ce registre soit d�j� utilis� et on pourrait �craser son contenu et provoquer des dysfonctionnements par la suite. Plain-\TeX{} propose la macro \idx\newtoks\verb-\<nom>- o� le \verb-\<nom>- sera une \idx{s�quence de contr�le} cr��e par \TeX{} et qui, par l'interm�diaire de la primitive \idx\toksdef, rendra \verb|\<nom>| �quivalent � \idx\toks suivi du prochain num�ro de registre inutilis�. Gr�ce � ce syst�me, on peut donc demander en toute s�curit� l'allocation d'un registre de tokens et y faire r�f�rence ensuite par un nom, ce qui est bien plus pratique � retenir qu'un num�ro.

Pour effectuer une assignation � un registre de tokens, il faut �crire

\centrecode-<registre de token>= {<ensemble de token>}-
\noindent ou bien
\centrecode-<registre de token>= <registre de token>-

\noindent o� \verb|<registre de token>| est soit une \idx{s�quence de contr�le} d�finie par \idx\toksdef ou \idx\newtoks, soit explicitement \idx\toks\verb|<num�ro>|. Le signe �=� et l'espace qui le suit sont facultatifs et seront souvent omis.

Pour extraire du registre ce qu'il contient, on doit faire appel � la primitive \idx\the suivie du \verb|<registre de token>|. Voici un exemple o� est sont cr��s deux registres \verb-\foo- et \verb|\bar| :

\showcode/\newtoks\foo% allocation d'un nouveau registre�\idx*\newtoks�
\foo={Bonjour le monde}% assignation
Contenu du registre {\tt\string\foo} : \the\foo.�\idx*\the\idx*\tt\idx*\string�

\newtoks\bar% allocation d'un autre registre
\bar=\foo% assigne � \bar les tokens du registre \foo
Contenu du registre {\tt\string\bar} : \the\bar.�\idx*\string�/

Comme pour les s�quences de contr�le, si l'assignation d'un registre � tokens se fait � l'int�rieur d'un groupe, elle est annul�e lors de sa fermeture � moins de faire pr�c�der l'assignation de \idx\global\idx*[|)]{registre!token}\idx*[|)]{token!registre}\idx*{assignation!registre de tokens}.

\chapter{Arguments d'une commande}
Les commandes vues jusqu'� pr�sent �taient immuables en ce sens que leur texte de remplacement �tait fig� une bonne fois pour toutes. Avec cette limite, elles ne seraient ni tr�s puissantes ni tr�s int�ressantes. Heureusement, les commandes peuvent admettre des � arguments �, variables eux, qui seront lus chaque fois que la commande sera appel�e et qui seront ins�r�s � des endroits du texte de remplacement choisis par l'utilisateur.

\section{\Qu 'est ce qu'un argument ?}

\begin{regle}
       Un \idx*{argument}argument d'une macro est :

       \begin{itemize}
               \item soit un \idx{token} c'est-�-dire un caract�re (un \idx{octet}) ou une \idx{s�quence de contr�le};
               \item soit le code qui se trouve entre deux accolades, �tant entendu que ce code est un ensemble de tokens �quilibr�s en accolades ouvrantes et fermantes.
       \end{itemize}
\end{regle}

\noindent Par exemple, si on les consid�re comme des arguments de commandes :
\begin{itemize}
       \item �\verb-a-� repr�sente un argument qui est �\verb-a-�;
       \item �\verb-abc-� repr�sente 3 arguments qui sont �\verb-a-�, �\verb-b-� et �\verb-c-�;
       \item �\verb*-ab c-� constitue 3 arguments aussi, les m�mes que ci-dessus. En effet, dans une liste d'arguments, un espace sous forme d'unit� lexicale est ignor�. Pour qu'il soit pris en compte l'espace \emph{doit} �tre mis entre accolades : �\verb*- -� n'est pas un argument alors que �\verb*-{ }-� en est un.
       \item �\verb-{abc}-� est un argument unique qui est �abc�;
       \item �\verb|\foo\bar|� sont deux arguments, �\verb|\foo|� et �\verb|\bar|�;
       \item �\verb|{\foo\bar}|� est un seul argument qui est �\verb|\foo\bar|�;
       \item enfin, �\verb*-{\def\AA{a}}{ }{c{d}e}{f}-� est constitu� de quatre arguments :
       \begin{enumerate}
               \item \verb-\def\AA{a}-
               \item \verb*- -
               \item \verb-c{d}e-
               \item \verb-f-
       \end{enumerate}
\end{itemize}

\label{argument.espace}\begin{regle}
Un espace \emph{non entour� d'accolades} est ignor� en tant qu'argument.\idx*[!argument]{espace}\idx*[!espace]{argument}
\end{regle}

Il faut retenir que les accolades ne servent qu'� d�limiter l'argument et n'en font pas partie. Lorsque \TeX{} lit cet argument, il lit le texte se trouvant � int�rieur des accolades et d�pouille donc l'argument de ses �ventuelles accolades ext�rieures\idx*[!d�limiteur d'argument]{accolade}.

\begin{regle}
Lorsque des accolades d�limitent un argument d'une macro, elles ne jouent pas le r�le de d�limiteur de \emph{groupe}\idx*{argument!accolades}.
\end{regle}\idx*[|(]{argument!accolades}

\begin{exercice}
Si on les consid�re comme arguments d'une macro, �\verb-a-� et �\verb-{a}-� sont-ils diff�rents ? Et si oui, en quoi ?
\solution
Non, s'ils sont les arguments d'une macro, �\verb-a-� et �\verb-{a}-� sont des arguments rigoureusement identiques et donc, si \verb|\foo| est une macro admettant un seul argument, il sera �quivalent d'�crire
\begin{itemize}
       \item \verb*|\foo a|
       \item \verb|\foo{a}|
\end{itemize}

En revanche, si l'on souhaite donner la macro \verb|\bar| comme argument, il y aura une diff�rence entre
\begin{itemize}
       \item \verb*|\foo\bar|
       \item \verb|\foo{\bar}|
\end{itemize}
Dans le premier cas, si un espace est � suivre, il sera ignor� tandis qu'il sera bien pris en compte dans le second cas puisque venant � la suite d'une accolade et non pas d'une \idx{s�quence de contr�le}.

Certains prennent l'habitude de ne jamais entourer d'accolades un argument constitu� d'une seule unit� lexicale. Il reste � savoir si cette habitude est bonne ou pas\ldots{} Je pencherais plut�t pour dire qu'elle est bonne puisqu'elle facilite la lisibilit� en ne surchargeant pas le code d'accolades inutiles. Cependant, la pr�sentation du code �tant souvent une affaire de gouts personnels, d'autres trouveraient des arguments imparables pour pr�f�rer le contraire !
\end{exercice}\idx*[|)]{argument!accolades}

Pour d�finir une commande qui admet des arguments\idx*{argument!token de param�tre (\char`\#)|etc}, on utilise le token �\cidx[ (token de param�tre)]\#�, de catcode \number\catcode`\#, dit �token de param�tre\idx*[!de param�tre]{token}� que l'on fait suivre d'un entier qui repr�sente le num�ro de l'argument. Cet entier doit �tre compris entre 1 et 9, ce qui signifie qu'une macro ne peut admettre que 9 arguments au maximum.

Voici une macro �\verb|\hello|�, tr�s simple, qui admet deux arguments et qui affiche � Bonjour \verb|<argument 1>| et \verb|<argument 2>|.� et qui compose le paragraphe courant � l'aide de \idx\par :

\showcode/\def\hello#1#2{Bonjour #1 et #2.\par}% d�finition
\hello ab% #1=a et #2=b
\hello a b% #1=a et #2=b
\hello{foo}{bar}% #1=foo et #2=bar
\hello foobar% #1=f et #2=o
% (le reste "obar" est lu apr�s que la macro est termin�e)/

Comme on le constate, �crire

\centrecode-\def\hello#1#2{Bonjour #1 et #2.\par}-

\noindent signifie que la commande \verb-\foo- admet deux arguments qui seront �crits �\verb-#1-� et �\verb-#2-� dans le \idx{texte de remplacement} de la macro. Lorsque \TeX{} va rencontrer \verb|\hello|, il lira \emph{aussi} les deux arguments qui suivent la commande. Il remplacera ces trois choses par le \idx{texte de remplacement} de la macro o� chaque \verb-#1- sera l'exact contenu du premier argument et chaque \verb-#2- celui du second.
\grandsaut

Lorsqu'on utilise \idx\def pour d�finir une macro, ce qui est situ� entre le nom de la macro et l'accolade ouvrante qui d�limite son texte de remplacement est appel� �\idx{texte de param�tre}�. Dans l'exemple ci-dessus, ce texte de param�tre est \verb-#1#2- et sp�cifie que la commande \verb-\foo- admet 2 arguments. Dans le texte de param�tre, les entiers qui suivent les caract�res \verb-#- doivent commencer � 1 pour le premier et aller en croissant de un en un. Il faut �galement que les arguments rencontr�s dans le \idx{texte de remplacement} existent \emph{aussi} dans le \idx{texte de param�tre} sinon, \TeX{} �met un message d'erreur �\verb|Illegal parameter number in definition of \<macro>|\footnote{Nombre de param�tres incorrect dans la d�finition de \texttt{\char`\\\codeelement{macro}}.}�. On ne peut donc pas �crire

\centrecode-\def\foo#1#2{Bonjour #1, #2 et #3}-

\noindent car l'argument \verb|#3| n'est pas sp�cifi� dans le \idx{texte de param�tre}.

\begin{regle}
Une macro peut accepter de 0 � 9 arguments\idx*{argument!nombre d'arguments}.

Pour le sp�cifier, on indique juste apr�s \idx\def, dans le �\idx{texte de param�tre}�, les arguments les uns � la suite des autres sous la forme �\verb|#1|�, �\verb|#2|�, et ainsi de suite jusqu'au nombre d'arguments que l'on veut donner � la macro.

Le \idx{texte de param�tre} est strict sur l'ordre des arguments, mais en revanche, il n'y a aucune contrainte sur l'ordre et l'existence des arguments dans le \idx{texte de remplacement} de la macro. On peut donc les y �crire dans l'ordre que l'on veut, autant de fois que l'on souhaite, voire ne pas en �crire certains.
\end{regle}

\begin{exercice}
Comment s'y prendre pour qu'une commande traite plus de 9 arguments, par exemple 10 ?

Programmer une macro \verb-\tenlist- qui lit 10 arguments (qui peuvent �tre par exemple les 10 premi�res lettres de l'alphabet) et les affiche de cette fa�on :

\begin{centrage}(a,b,c,d,e,f,g,h,i,j)\end{centrage}

\solution
On ne peut pas, \emph{stricto sensu}, programmer une macro qui admet 10 arguments, c'est une limitation intrins�que � \TeX. Mais rien n'emp�che d'en programmer une qui admet 9 arguments, traiter ces arguments comme on l'entend et une fois fini, passer la main � une autre commande qui admettra un argument, le lira et le traitera � son tour.

On va donc �crire :

\centrecode-\def\tenlist#1#2#3#4#5#6#7#8#9{%
       (#1,#2,#3,#4,#5,#6,#7,#8,#9\endlist
}
\def\endlist#1{,#1)}-

Lorsque \TeX{} rencontrera la macro \verb-\tenlist-, il l'absorbera ainsi que les 9 arguments suivants (et uniquement eux) et il aura donc avanc� juste devant le 10\ieme{} argument. Il proc�dera � la substitution de la macro et ses arguments par le texte de remplacement et poursuivra sa lecture en tenant compte de la substitution. Ce texte de remplacement va proc�der � l'affichage des 9 premiers arguments en les s�parant par une virgule, puis \TeX{} rencontrera � la fin du \idx{texte de remplacement} la macro \verb-\endlist-. Comme elle n'est suivie de rien dans le texte de remplacement, elle ira chercher son argument plus loin dans le code, et ce qu'il y a apr�s justement, c'est le 10\ieme{} argument.

\showcode/\def\tenlist#1#2#3#4#5#6#7#8#9{(#1,#2,#3,#4,#5,#6,#7,#8,#9\endlist}
\def\endlist#1{,#1)}
Une liste \tenlist abcdefghij de lettres./
\end{exercice}

Voici l'exemple de la macro \verb-\foo- que l'on a d�fini pr�c�demment et que l'on met � l'�preuve dans diff�rents cas :

\showcode/\def\foo#1#2{Bonjour #1 et #2.\par}
\begingroup\tt% passer en fonte � chasse fixe�\idx*\begingroup\idx*\tt�
a) \foo{monsieur}{madame}
b) \foo{{\bf toi}}{moi}
c) \foo{}{{}}
d) \foo{ }{ }
e) \foo{$\pi$} {$\delta$}
f) \foo ab
g) \foo X       Y
\endgroup% fin de la fonte � chasse fixe�\idx*\endgroup�/

\noindent Le cas b contient un argument lui-m�me entre accolades, c'est-�-dire dans un groupe. En effet, si les accolades int�rieures n'existaient pas, cet argument serait �\verb-\bf moi-� et la macro \idx\bf qui ordonne le passage en fonte grasse ne serait pas contenue dans un groupe pour en limiter sa port�e. Tel qu'il est �crit � la ligne 4, le second argument est donc \verb-{\bf moi}- et donc le texte de remplacement de \verb-\foo{toi}{{\bf moi}}- est :

\centrecode-Bonjour toi et {\bf moi}.\par-

On remarque ensuite au cas c que les deux arguments ne produisent rien. Le premier parce que c'est un
\idx[!vide]{argument} vide et le second parce que c'est \verb-{}- qui est un groupe vide qui lui non plus ne produit non plus aucun affichage. Pour mieux comprendre ce qui se passe � cette ligne 5, le texte de remplacement de \verb-\foo{}{{}}- est :

\centrecodespc-Bonjour  et {}.\par-

L'argument \verb|#1|, qui est vide, se trouve entre les deux premiers espaces qui par cons�quent deviennent des espaces cons�cutifs, mais ils ne le sont pas \emph{dans le code source} ! La r�gle de \TeX{} concernant les \idx[!cons�cutifs]{espace} cons�cutifs ne s'applique donc pas comme on peut l'observer � l'affichage.

\begin{regle}
Si l'argument \verb|<i>| d'une macro est vide, cela �quivaudra dans le texte de remplacement de la macro � ce que \verb-#<i>- n'existe pas\idx*{argument!vide}.
\end{regle}

Le sens d'un argument �vide� n'est pas �vident. On entend ici que l'argument vide est ce qui est entre les accolades dans �\verb-{}-�. Si l'on pr�f�re, un argument vide n'est constitu� d'aucun token.

Ce qui se passe au cas d est tout aussi int�ressant. Les deux arguments sont des espaces \emph{entre accolades}, ils sont donc pris en compte. Le texte de remplacement est ici :

\begin{centrage}
\small\verb*-Bonjour -\fboxsep0.5pt\fbox{\ttfamily\vphantom A\textvisiblespace}\verb*- et -\fbox{\ttfamily\vphantom A\textvisiblespace}\verb-.-
\end{centrage}

\noindent Les arguments \verb-#1- et \verb-#2-, qui sont des espaces, ont �t� encadr�s. L'espace du code �\verb*- -�, suivi de l'espace qui provient de l'argument {\fboxsep0.5pt\fbox{\ttfamily\vphantom A\textvisiblespace}}, ne sont pas des espaces cons�cutifs \emph{du code}. La r�gle qui veut que deux espaces cons�cutifs du code n'en font qu'un \emph{ne s'applique pas}. � l'affichage, on a donc \emph{trois} espaces entre �Bonjour� et �et� puis deux entre �et� et le point final.
\grandsaut

Lorsque \TeX{} lit le \idx{texte de param�tre} puis le \idx{texte de remplacement} d'une macro pour la d�finir et stocker les tokens qui r�sultent de cette lecture, il entre dans ce qu'on appelle la \emph{\idx{lecture � grande vitesse}}. Tr�s peu de v�rifications sont faites � ce moment :

\begin{enumerate}
       \item dans le \idx{texte de param�tre}, la d�claration des arguments \verb|#<chiffre>| n'est accept�e que si les \verb|<chiffres>| commencent � 1 et vont en croissant de un en un;
       \item une occurrence de \verb|#<chiffre>| dans le \idx{texte de remplacement}, symbolisant l'emplacement d'un argument, est accept�e uniquement si cet argument a �t� d�clar� dans le \idx{texte de param�tre};
       \item \TeX{} v�rifie que les macros rencontr�es dans le \idx{texte de remplacement} ne sont pas d�clar�es �\idx\outer� (voir page~\pageref{outer});
       \item la \idx{lecture � grande vitesse} s'arr�te lorsque l'accolade ouvrante marquant le d�but du \idx{texte de remplacement} est �quilibr�e par une accolade fermante. � ce moment, le stockage du \idx{texte de remplacement} sous forme de tokens a lieu dans la m�moire de \TeX.
\end{enumerate}

L'argument d'une commande ne peut pas contenir la primitive \idx\par. Cette interdiction est en fait un m�canisme de s�curit� pour que, si jamais on a oubli� de fermer l'accolade qui marque la fin d'un argument, \TeX{} ne tente pas de lire ind�finiment (jusqu'� la fin du document) cet argument : au premier \idx\par rencontr�, la compilation est stopp�e avec affichage d'un message d'erreur, ce qui limite la zone o� l'on doit chercher o� il manque une accolade fermante dans le code source. Il est parfois n�cessaire de passer outre cette protection si l'on souhaite �crire une macro dont un argument est susceptible de contenir \idx\par. Pour d�clarer une macro de ce type, il faut faire pr�c�der \idx[|etc]\def\forbidindex\def{} de la primitive \idx\long. Dans ce cas, on dit que la macro est � longue � par opposition aux autres macros � courtes �.

Il faut noter que si on d�finit un alias pour \idx\par comme plain-\TeX{} le fait avec \verb-\let\endgraf=\par-, alors, l'alias \idx\endgraf est permis dans l'argument d'une macro m�me si celle-ci n'est pas d�clar�e \idx\long. En effet, les arguments d'une macro sont eux aussi lus � grande vitesse\idx*{lecture � grande vitesse} avant d'�tre ins�r�s sous forme de tokens aux endroits qui leur sont r�serv�s dans le texte de remplacement. Lors de cette \idx{lecture � grande vitesse}, \TeX{} ne tient pas compte de la \verb|\let| �galit�; il ne fait que chercher \verb|\par|. L'alias \verb|\endgraf| est parfois bien pratique puisqu'avec cet artifice, tout se passe comme si l'on pouvait mettre un \verb|\par| dans les macros courtes sans avoir besoin de les r��crire pour qu'elles soient longues.

\begin{regle}
Une macro ne peut admettre la primitive \idx\par dans aucun de ses arguments. Elle admet en revanche toute \idx{s�quence de contr�le} \verb|\let|-�quivalente � \verb|\par|, par exemple \idx\endgraf, d�finie par plain-\TeX.

Pour d�finir une macro capable d'accepter \idx\par dans ses arguments, on doit faire pr�c�der \verb|\def| de la primitive \idx\long.
\end{regle}

\section{Perte d'informations lors de la � tok�nization �}\label{perte.information.lecture}
Examinons maintenant comment et quand sont lues les � composantes � d'une macro, � savoir son texte de remplacement et ses arguments, et surtout quelles sont les cons�quences de cette lecture.

Tout d'abord, il est utile de comprendre que plusieurs moments diff�rents interviennent lorsqu'on utilise une macro :

\begin{itemize}
       \item le moment o� elle est d�finie;
       \item le (ou les) moment(s) o� elle est appel�e.
\end{itemize}

\begin{regle}
Lorsqu'une macro est \emph{d�finie}, les arguments figurant dans le \idx{texte de remplacement} sous la forme \verb|#<chiffre>| (o� �\verb|#|� symbolise un token ayant le catcode \number\catcode`\#\relax{} au moment de la d�finition) sont des endroits o� \TeX{} mettra les arguments lus plus tard lorsque la macro sera appel�e.

Lors de sa \idx{lecture � grande vitesse}, le reste du texte de remplacement est � tok�niz� � c'est-�-dire que les caract�res composant le code source sont transform�s en tokens et les catcodes qui leur sont assign�s ob�issent au r�gime en cours lorsque la d�finition a lieu. Ces tokens sont stock�s dans la m�moire de \TeX.
\medskip

Lorsqu'une macro est \emph{appel�e} et qu'elle \emph{lit} ses arguments, ceux-ci sont lus � grande vitesse\idx*{lecture � grande vitesse} et sont tok�niz�s selon le r�gime de catcode en vigueur cette macro est appel�e (et qui peut donc diff�rer de celui en cours lors de sa d�finition). Ils sont ensuite ins�r�s aux endroits o� \verb|#<chiffre>| �tait �crit dans le texte de remplacement. Les tokens du \idx{texte de remplacement} ne sont pas modifi�s et restent ce qu'ils �taient lors de la d�finition.
\end{regle}

Plus g�n�ralement, quels que soient le moment et les circonstances, lorsque \TeX{} lit du code source, les caract�res du code source sont transform�s en tokens. Cette transformation est faite selon le r�gime de catcode en vigueur au moment de la lecture et des r�gles sp�cifiques � chaque cat�gorie sont alors appliqu�es. Il est important de savoir que transformer des caract�res en tokens provoque d'irr�versibles pertes d'informations. En voici quelques-unes :

\begin{enumerate}
       \item plusieurs \idx[!cons�cutifs]{espace}s cons�cutifs sont lus comme un espace unique;
       \item les \idx[!d�but de ligne]{espace}s au d�but d'une ligne du code source sont ignor�s ;
       \item les espaces qui suivent une \idx{s�quence de contr�le} sont ignor�s;
       \item un caract�re de \idx*{catcode!5 (retour charriot)}catcode 5 (en g�n�ral le retour charriot �\verb|^^M|�) est lu comme un espace\idx*[!5 (retour charriot)]\catcode\verbidx*[ (retour charriot)]{^^M};
       \item deux caract�res cons�cutifs de catcode 5 sont lus comme la primitive \idx\par\verbidx*[ cons�cutifs]{^^M};
       \item deux caract�res identiques de catcode \number\catcode`\^{}\idx*{catcode!7 (exposant)} (en g�n�ral le caract�re de mise en exposant �\verb|^|�) suivis d'un caract�re ou de deux chiffres hexad�cimaux sont lus comme un caract�re unique\verbidx*{^^}\iffalse i\fi;
       \item le caract�re de code \idx\endlinechar est ins�r� � chaque fois qu'une \idx{fin de ligne} de code source est rencontr�e ;
       \item dans une ligne de code source, tout ce qui se trouve apr�s un caract�re de catcode \number\catcode`\%{} est ignor� (le caract�re de commentaire est en g�n�ral �\cidx\%�).
\end{enumerate}

Par exemple, supposons qu'une macro \verb|\foo| est d�finie de cette fa�on sous le r�gime de catcode par d�faut :

\centrecodespc|\def\foo{Programmer  en \TeX {} est   facile}|

\noindent Par la suite, en examinant le texte de remplacement de \verb|\foo|, il est impossible de savoir combien d'espaces il y avait apr�s �\texttt{est}� dans le code source. Il est �galement impossible de savoir si \verb|\TeX| �tait suivi d'un espace, de plusieurs ou d'aucun. Et donc, une fa�on \emph{strictement �quivalente} de d�finir \verb|\foo| aurait �t� :

\centrecodespc|\def\foo{Program^^6der en   \TeX{} est facile}|

La primitive \idx\meaning peut nous aider � le constater.

\showcode|\def\foo{Programmer  en \TeX {} est   facile}
\meaning\foo\par�\idx*\meaning�
\def\foo{Program^^6der en   \TeX{} est facile}
\meaning\foo�\idx*\meaning�|

\begin{regle}
Lorsque \TeX{} lit du code source, d'irr�versibles pertes d'informations ont lieu lorsque des \emph{caract�res} sont transform�s en \emph{\idx{token}s}.
\end{regle}

Cette r�gle s'applique bien �videmment lorsque \TeX{} lit du code pour le stocker (que ce soit dans une macro ou dans un registre de tokens) ou pour l'ex�cuter.

\begin{exercice}
Donner un autre exemple de perte d'information lorsque \TeX{} lit du code.
\solution
Si deux caract�res ont le catcode 0\idx*{catcode!0 (caract�re d'�chappement)} (par exemple �\verb|\|� et �\verb-|-�), voici deux fa�ons parfaitement �quivalentes de d�finir une macro \verb|foo| :

\centrecodespc-\def\foo{Programmer en |TeX{} est facile}-

\noindent et

\centrecodespc-\def\foo{Programmer en \TeX{} est facile}-

Si par ailleurs, "\verb|<|" et "\verb|>|" ont comme catcode 1\idx*{catcode!1 (accolade)} et 2, alors, cette fa�on est �galement �quivalente :

\centrecodespc*-\def\foo<Programmer en \TeX<> est facile}-

Une autre perte d'information est que les caract�res ayant un catcode �gal � 9 sont ignor�s.
\end{exercice}

\begin{exercice}
Comment faudrait-il s'y prendre pour que la lecture du code soit \emph{r�versible}, c'est-�-dire pour qu'aucune perte d'information n'ait lieu ?
\solution
Il faudrait que le r�gime de catcode en vigueur soit tr�s sp�cifique et que tous les caract�res ayant un catcode de 0, 1, 2, 5, 6, 9, 10, 13, 14 et 15 aient un catcode de 12. On peut aussi carr�ment utiliser le r�gime o� \emph{tous} les octets ont un catcode �gal � 12.
\end{exercice}

\section{\Qu elques commandes utiles}
Prenons maintenant le temps de d�finir des commandes utiles en programmation. Certes, il est encore t�t pour comprendre leur int�r�t, mais nous le verrons plus tard, leur emploi est fr�quent.

La plus simple de toutes est pourtant tr�s utile : elle lit un argument qu'elle fait disparaitre. Appelons-la\footnote{Cette macro est appel�e {\ttfamily\string\@gobble} dans le noyau \LaTeX.} �\gobone pour �gobble one� qui signifie �mange un�. Le code qui permet sa d�finition est d'une simplicit� extr�me :

\centrecode-\def\gobone#1{}-

\noindent Le texte de remplacement est vide, ce qui revient � dire que lorsque \TeX{} rencontre \verb-\gobone-, il lit �galement l'argument qui suit et remplace le tout par le texte de remplacement, c'est-�-dire rien.

Pour rester dans la simplicit�, voici une commande qui admet un argument et dont le texte de remplacement est cet argument. Appelons-la\footnote{Son nom dans le noyau \LaTeX{} est \texttt{\string\@firstofone}} �\identity\label{identity} :

\centrecode-\long\def\identity#1{#1}-

Voici maintenant deux commandes tr�s utilis�es. Elles admettent deux arguments. Le texte de remplacement de �\firstoftwo est son premier argument et celui �\secondoftwo est son second argument\footnote{Elles sont appel�es \texttt{\string\@firstoftwo} et \texttt{\string\@secondoftwo} dans le noyau \LaTeX.}\label{firstoftwo}

\centrecode-\long\def\firstoftwo#1#2{#1}
\long\def\secondoftwo#1#2{#2}��*\secondoftwo�-

On pourrait aller plus loin et d�finir, pourquoi pas, \verb|\thirdofsix| qui irait chercher le 3\ieme{} argument d'une s�rie de 6 :

\centrecode-\long\def\thirdofsix#1#2#3#4#5#6{#3}-

\noindent Mais ces variantes sont un peu inutiles, car ce sont les macros �\firstoftwo et �\secondoftwo qui sont le plus souvent utilis�es. Pourquoi est-il plus utile et fr�quent de choisir entre \emph{deux} arguments ? L'explication tient au fait que ces macros sont utilis�es apr�s un test pour choisir une des alternatives, l'une correspondant au fait que le test est vrai et l'autre qu'il est faux.

\begin{exercice}
Pour manger les deux arguments \verb-{<arg1>}- et \verb-{<arg2>}-, le code suivant ne fonctionne pas :
\centrecode-\gobone\gobone{<arg1>}{<arg2>}-

Pourquoi ? Comment faudrait-il programmer la macro �\gobtwo pour qu'elle mange et fasse disparaitre les deux arguments qui la suivent ?
\solution
\TeX{} lit le code \emph{de gauche � droite}, il remplace donc dans un premier temps �\gobone et son argument, le deuxi�me �\gobone, par le texte de remplacement de �\gobone, c'est-�-dire rien. Les deux �\gobone disparaissent et il reste les deux arguments entre accolades qui seront affich�s tous les deux !

La macro �\gobtwo se programme ainsi : \verb-\def\gobtwo#1#2{}-
\end{exercice}

\begin{exercice}
\Qu 'obtient-on � l'affichage si on �crit :

\centrecode-\gobone1\secondoftwo2{3\gobtwo}\firstoftwo45\secondoftwo{67}{\gobone890}��*\secondoftwo�-

\solution
Proc�dons de gauche � droite, comme \TeX{} :
\begin{itemize}
       \item �\verb-\gobone 1-� disparait;
       \item �\verb-\secondoftwo2{3\gobtwo}-� a comme texte de remplacement son 2\ieme{} argument qui est �\verb-3\gobtwo-�. �3� est donc affich� et le \verb-\gobtwo- va manger les 2 arguments qui le suivent. Ils se trouvent en dehors de l'argument en cours et ce sont ��\firstoftwo\verb-4-� qui sont donc mang�s;
       \item �5� est affich�;
       \item �\verb-\secondoftwo{67}{\gobone890}-� a pour texte de remplacement son 2\ieme{} argument qui est �\verb-\gobone890-�. Le \verb|\gobone| mange le �8� qui disparait et il reste donc les tokens �90� qui seront affich�s.
\end{itemize}

On obtient donc �\verb-3590-�
\end{exercice}
\begin{exercice}
On constate que les macros �\gobone et �\secondoftwo donnent les m�mes r�sultats :

\showcode/a) \gobone XY - \secondoftwo XY\par��*\gobone�*\secondoftwo�
b) \gobone{ab}{xy} - \secondoftwo{ab}{xy}\par
c) \gobone{123}4 - \secondoftwo{123}4\par
d) \gobone A{BCD} - \secondoftwo A{BCD}��*\gobone�*\secondoftwo�/

Existe-t-il une diff�rence entre les macros �\gobone et �\secondoftwo et si oui, laquelle ?
\solution
Il y a une diff�rence, et de taille! On peut le voir sur cet exemple :

\showcode/\gobone     {a}{\catcode`\~12 Le <<~>> est un espace ?} Et ici <<~>> ?�\cidx*\~�

\secondoftwo{a}{\catcode`\~12 Le <<~>> est un espace ?} Et ici <<~>> ?��*\secondoftwo�/

� la premi�re ligne, lorsque �\gobone est d�velopp�e, �\verb|\gobone{a}|� disparait et il reste ceci qui n'a pas encore �t� lu :

\centrecode*-{\catcode`\~12 Le <<~>> est un espace ?} Et ici <<~>> ?-

Il est clair que la modification de catcode a lieu \emph{� l'int�rieur d'un groupe} et que dans ce groupe, \cidx\~ devient un caract�re � autre � que l'on peut afficher tel quel. En revanche, une fois sorti du groupe, il reprend son catcode naturel de 13 et redevient donc actif pour afficher une espace ins�cable.

Tout est diff�rent dans la deuxi�me ligne. La macro �\secondoftwo lit ses \emph{deux} arguments et �redonne� le second une fois qu'il a �t� lu. Voici donc ce qu'il reste apr�s que �\secondoftwo ait �t� remplac� pare son 2\ieme{} argument :

\begin{centrage}
       \small\ttfamily\fboxsep2pt\fbox{\string\catcode`\string\~12 Le <{}<\string~>{}> est un espace \string?} \Verb|Et ici <<~>> ?|
\end{centrage}

Le 2\ieme{} argument, ici encadr� et qui s'�tend jusqu'au premier �\string?� a �t� lu par �\secondoftwo et donc, le \idx{catcode} de �\string~� est fig� � 13. Par cons�quent, �\string~� gardera dans tout l'argument encadr� le \idx{catcode} 13\idx*{catcode!13 (actif)} qu'il avait lorsque �\secondoftwo a �t� appel�. L'ordre \idx\catcode\verb|`\~12| rencontr� dans l'argument ne pourra agir qu'apr�s cet argument : \cidx\~ prendra donc le \idx{catcode} 12\idx*{catcode!12 (autre)} apr�s la fin de l'argument et ce en-dehors de tout groupe. Il gardera donc ce \idx{catcode} ind�finiment c'est-�-dire jusqu'� ce qu'il soit volontairement modifi�.
\grandsaut

Pour r�sumer :
\begin{itemize}
       \item de ��\gobone\verb|{<a>}{<b>}|�, il reste \verb|{<b>}|qui n'est pas encore lu;
       \item tandis que �\secondoftwo\verb|{<a>}{<b>}| lit le second argument, le d�pouille de ses accolades et le tout devient donc \verb|<b>| o� les catcodes sont fig�s.
\end{itemize}
\end{exercice}

\begin{exercice}
Le but est d'afficher l'�nonc� et la correction d'une courte interrogation de grammaire �l�mentaire, tous deux stock�s dans la macro \verb-\interro- ainsi d�finie :

\centrecode-\def\interro{J'ai �t\?{�} invit\?{�} � go�t\?{er} chez Max.
            On s'est bien amus\?{�} et ensuite, il a fallu
            rentr\?{er}.}-

�crire une macro \verb-\?- qui admet un argument. Cet argument sera affich� tel quel si la commande \verb-\visible- a �t� rencontr�e auparavant, et si c'est la commande \verb-\cache-, cet argument sera remplac� par �...�. Les commandes \verb-\cache- et \verb-\visible- n'admettent pas d'argument.

On �crira �\verb-\cache\interro-� ou �\verb-\visible\interro-� selon que l'on souhaite afficher l'�nonc� ou la correction.
\solution
L'id�e est que le texte de remplacement de \verb-\?{<argument>}- doit �tre

\centrecode-\choix{<argument>}{...}-

\noindent o� \verb-\choix- sera rendu �gal � �\firstoftwo par \verb-\visible- et � �\secondoftwo par \verb-\cache- :

\showcode/\def\visible{\let\choix=\firstoftwo}��*\firstoftwo�
\def\cache{\let\choix=\secondoftwo}��*\secondoftwo�
\def\?#1{\choix{#1}{...}}%
\def\interro{J'ai �t\?{�} invit\?{�} � gout\?{er} chez Max. Apr�s s'�tre
            bien amus\?{�}, nous avons rang\?{�} et il a fallu rentr\?{er}.}
Compl�ter avec << � >> ou << er >> :\par
\cache\interro\par\medskip�\idx*\medskip�
Correction :\par
\visible\interro/
\end{exercice}

\section{D�finitions imbriqu�es}
� l'exercice pr�c�dent, on aurait pu proc�der de fa�on plus � �conomique �, sans avoir besoin de d�finir une macro auxiliaire \verb|\choix|. La macro \verb|\visible| aurait pu �tre programm�e pour d�finir \verb|\?| \idx\let{}-�gale � �\identity (qui affiche son argument tel quel) alors que la macro \verb|\cache| aurait d�fini la macro \verb|\?| de cette fa�on :

\centrecode-\def\?#1{...}-

\noindent Mais si on �crit

\centrecode-\def\cache{\def\?#1{...}}-

\noindent \TeX{} �met un message d'erreur : �\texttt{Illegal parameter number in definition of \string\cache}�. L'explication est que l'argument \verb|#1| est compris comme �tant celui de la macro \emph{ext�rieure} \verb|\cache| et non pas comme celui de la macro int�rieure \verb|\?|. L'erreur survient, car la macro ext�rieure \verb|\cache| est d�finie comme n'ayant \emph{aucun} argument.

Lorsque des d�finitions de macros sont imbriqu�es, la r�gle veut que pour distinguer les arguments des macros, il faut doubler les tokens de param�tre \verb|#| � chaque niveau d'imbrication suppl�mentaire. Ainsi, la bonne fa�on de d�finir \verb|\cache| est :

\centrecode-\def\cache{\def\?##1{...}}-

Voici le code complet :

\showcode/\def\visible{\let\?=\identity}��*\identity�
\def\cache{\def\?##1{...}}
\def\interro{J'ai �t\?{�} invit\?{�} � go�t\?{er} chez Max. On s'est
            bien amus\?{�} et ensuite, il a fallu rentr\?{er}.}
Compl�ter avec << � >> ou << er >> :\par
\cache\interro\par\medskip�\idx*\medskip�
Correction :\par
\visible\interro/

\begin{regle}
Lorsqu'on d�finit une macro � fille �\idx*{macro fille} dans le \idx{texte de remplacement} d'une macro � m�re �, les \verb-#- concernant les arguments de la macro fille sont doubl�s, aussi bien dans le \idx{texte de param�tre} que dans le \idx{texte de remplacement}.

Ils seront doubl�s � nouveau � chaque imbrication
suppl�mentaire pour �viter de confondre les arguments des macros imbriqu�es.
\end{regle}
\grandsaut

� la lumi�re de ce qui vient d'�tre dit, examinons maintenant le code suivant :

\centrecodespc-\def\makemacro#1#2{\def#1##1{##1 #2}}-

On constate que \verb|\makemacro| admet deux arguments et que le premier est n�cessairement une \idx{s�quence de contr�le} puisque cet argument \verb|#1| se trouve juste apr�s le \verb|\def| dans le texte de remplacement.

Faisons mentalement fonctionner la macro \verb|\makemacro| lorsqu'on l'appelle de cette fa�on : \verb|\makemacro\foo{BAR}|. Comme on le sait, le texte de remplacement de ce code va �tre obtenu en rempla�ant chaque \verb|#1| par \verb|\foo| et chaque \verb|#2| par \verb|BAR| ce qui donne :

\centrecodespc-\def\foo##1{##1 BAR}-

\noindent Puisqu'on examine le code contenu dans le texte de remplacement, il devient inutile de doubler les tokens de param�tre et donc, tout se passe donc comme si la macro \verb|\foo| �tait d�finie par :

\centrecodespc-\def\foo#1{#1 BAR}-

Le code obtenu ne pr�sente pas de difficult� particuli�re, l'argument \verb|#1| de \verb|\foo| est plac� devant l'argument \verb|#2| de \verb|\makemacro| qui est \verb|BAR|. Par exemple, si l'on �crivait �\verb-\makemacro\mai{mai 2014}-�, alors par la suite, \verb-\mai{10}- aurait comme texte de remplacement �\texttt{10 mai 2014}�.

\showcode/\def\makemacro#1#2{\def#1##1{##1 #2}}
\makemacro\LL{Lamport}
\makemacro\juin{juin 2014}
Paris, le \juin{3}.\medbreak�\idx*\medbreak�
\LL{Cher Monsieur},\smallbreak�\idx*\smallbreak�
Vous �tes convoqu� � un examen sur \TeX{} le \juin{21} �
9h00 pr�cise dans le bureau de D. Knuth.\smallbreak�\idx*\smallbreak�
Veuillez croire, \LL{Monsieur}, en mes sentiments \TeX iens./

\section{Programmer un caract�re actif}
Le niveau de \TeX nicit� atteint dans cette section est plut�t relev�. On pourra donc, lors d'une premi�re lecture, se dispenser de se plonger dans cette section, quitte � y revenir plus tard.
\grandsaut

Avant de rentrer dans le vif du sujet, rappelons ce qu'est r�ellement un caract�re. Aux yeux de \TeX{} lorsqu'il le lit, un caract�re (c'est-�-dire un token n'�tant pas une \idx{s�quence de contr�le}) est constitu� de :
\begin{itemize}
       \item un code dit �\idx{code de caract�re}� qui repr�sente l'ordre du caract�re dans la table des caract�res. Par exemple, le caract�re �\verb|A|� a le code de caract�re \number`A{} tandis que �\verb|^|� a le code \number`\^. Il y a 256 codes\footnote{Pour les moteurs 8 bits, il y a effectivement 256 codes possibles. En revanche, pour les moteurs \utf, il y a en a bien plus.} possibles;
       \item un code dit �code de cat�gorie� ou �catcode� qui met le caract�re dans une des 16 cat�gories et lui conf�re les propri�t�s communes � tous les caract�res de cette cat�gorie. Ainsi, �\verb|A|� a le code de cat�gorie \number\catcode`A, et �\verb|^|� le code de cat�gorie \number\catcode`\^.
\end{itemize}

Chaque caract�re lu poss�de donc intrins�quement une \emph{paire de codes}. On peut convenir d'une notation et les mettre entre parenth�ses, le premier �tant le code de caract�re et le second le catcode. Cela donnerait : \showcodes{A} et \showcodes^.
\grandsaut

L'objet ici est de d�couvrir comment on peut programmer une macro --~appelons-la �\defactive~-- qui rend actif un caract�re choisi par l'utilisateur et qui lui donne un texte de remplacement donn�. Ainsi, �\verb-\defactive W{wagons}-� fera qu'apr�s cet appel, le caract�re �\verb|W|� sera actif et son texte de remplacement sera �wagons�.

Comme nous l'avons vu, si on modifie un catcode dans le texte de remplacement d'une macro, la modification n'entrera en vigueur qu'apr�s ce texte de remplacement. En effet, la r�gle vue � la page~\pageref{catcode.inalterable} veut que lorsqu'un argument est lu, les catcodes des tokens qui le composent sont fig�s. Il est donc exclu de programmer la macro de cette fa�on

\centrecode-\def\defactive#1#2{\catcode`\#1=13 \def#1{#2}}-�*\defactive

\noindent car, malgr� l'ordre \verb|\catcode`\#1=13|, le catcode de \verb-#1- ne serait pas modifi� � l'int�rieur du texte de remplacement de �\defactive. Par exemple, si \verb-#1- est �\verb|W|�, son catcode restera 11 (celui que \verb|W| a par d�faut) et \TeX{} va �chouer lorsqu'il rencontrera \verb|\def|\verb- W{wagons}-, car �\verb|W|� ne sera pas encore actif.

�videmment, on l'a vu aussi, on pourrait utiliser un \idx\gdef et agir dans un groupe o� l'on aurait d�j� modifi� le catcode de �\verb|W|� � 13. Cette m�thode est possible lorsqu'on conna�t \emph{� l'avance} le caract�re � rendre actif. Or, ce n'est pas le cas ici puisque l'argument \verb-#1- de la macro est choisi par l'utilisateur.
\grandsaut

Int�ressons-nous par exemple � la primitive \idx\lowercase{} car les fonctionnements de \idx\lowercase{} et \idx\uppercase{} sont sym�triques : il suffit de comprendre comment fonctionne l'une pour comprendre comment fonctionne de l'autre.

Avant d'entrer dans le vif du sujet, il faut mentionner qu'en plus du code de cat�gorie et du code de caract�re, chaque caract�re poss�de deux autres codes :

\begin{itemize}
       \item le \idx{code minuscule} accessible par la primitive \idx\lccode;
       \item le \idx{code majuscule} accessible par la primitive \idx\uccode.
\end{itemize}

Par exemple, le code de caract�re de la lettre �A� est {\number`\A} et son code minuscule est {\number`\a} qui est celui de la lettre �a�. Il en est ainsi pour chaque lettre majuscule de l'alphabet qui poss�de un code minuscule correspondant � celui de la lettre minuscule. Gr�ce � la primitive \idx\the ou \idx\number, on peut afficher les codes de caract�re et les codes minuscules des lettres A, B, et m�me de a, b. On va utiliser ici une macro \verb-\showcodes- pour all�ger le code :

\showcode/\def\showcodes#1{\string#1 : $\number`#1 \rightarrow \number\lccode`#1$}�\idx*\string\idx*\number\idx*\rightarrow\idx*\the\idx*\lccode�
\showcodes A\qquad \showcodes B\qquad�\idx*[|etc]\qquad\forbidindex\qquad�
\showcodes a\qquad \showcodes b\qquad \showcodes ^/

On observe que logiquement, le \idx{code minuscule} de �a� est le sien propre. \Qu ant au code minuscule de �\verb|^|�, il est �gal � 0 ce qui signifie que ce caract�re n'a pas de code minuscule pr�d�fini.

\begin{regle}
La primitive \idx\lowercase doit �tre suivie de son argument entre accolades et cet argument, constitu� d'un texte dont les accolades sont �quilibr�es, est lu de la fa�on suivante :

\begin{itemize}
       \item les s�quences de contr�les restent inchang�es;
       \item pour chaque caract�re, le code de caract�re est remplac� par le \idx{code minuscule}, �tant entendu que le code de cat�gorie \emph{ne change pas}.

       Si le code minuscule d'un caract�re est nul, ce caract�re n'est pas modifi� par \idx\lowercase.
\end{itemize}
\end{regle}

Voici la primitive \idx\lowercase en action :

\showcode/\lowercase{CACAO foobar}\par�\idx*\lowercase�
\lowercase{\def\foo{Bonjour}}% d�finit une commande \foo
\foo % la commande d�finie pr�c�demment/

On peut d�tourner la primitive \idx\lowercase de son usage premier qui est de mettre un texte en minuscule. Pour cela, il suffit de modifier le code minuscule d'un caract�re. Supposons que nous souhaitions que le \idx{code minuscule} de �A� ne soit plus {\number`\a} qui est celui de la lettre �a�, mais {\number`\*} qui est celui de �\verb-*-�. Pour cela, il va falloir modifier le \idx\lccode de �A� � l'int�rieur d'un groupe semi-simple, puisqu'il est toujours prudent de confiner les modifications lorsqu'on touche aux m�canismes internes de \TeX{} :

\showcode/\begingroup�\idx*\begingroup�
       \lccode`A=`* % change le code minuscule de A�\idx*\lccode�
       \lowercase{CACAO ABRACADABRA}\par�\idx*\lowercase�
\endgroup�\idx*\endgroup�
\lowercase{CACAO ABRACADABRA}/

Les �*� que l'on obtient ont le catcode de A, c'est-�-dire 11.

\begin{regle}
Si l'on �crit �\verb|\lccode<entier1>=<entier2>|� alors, dans l'argument de \verb|\lowercase|, tous les caract�res de code \verb|<entier1>| seront lus comme des caract�res de code \verb|<entier2>| tout en gardant leur catcode originel.

En pratique, si l'on �crit

\centrecode-\lccode`\<car1>=`\<car2>-

puis

\centrecode-\lowercase{<texte>}-

alors, dans le \verb|<texte>|, tous les \verb|<car1>| sont lus comme \verb|<car2>|, mais en conservant le catcode de \verb|<car1>|.
\end{regle}

Nous sommes pr�ts pour �crire la macro �\defactive et nous allons exploiter le fait que le caract�re �\cidx\~� est naturellement actif. Gr�ce � la primitive \idx\lowercase, on va le transformer dynamiquement pour qu'il devienne le caract�re \verb-#1- \emph{actif} de notre macro �\defactive :

\centrecode|\def\defactive#1#2{%��*\defactive�
   \catcode`#1=13 % #1 sera actif apr�s la fin
                  % du texte de remplacement
   \begingroup
   \lccode`~=`#1  % dans \lowercase, changer les ~ (actifs)
                  % en "#1", ceux-ci �tant actifs
   \lowercase{\endgroup\def~}{#2}%
}|

\begin{itemize}
       \item �\idx\catcode\verb|`#1=13|�\idx*[!13 (actif)]\catcode rend le caract�re \verb-#1- actif, mais comme nous l'avons vu, cette modification n'entrera en vigueur qu'apr�s �tre sorti du texte de remplacement;
   \item Le \idx\endgroup n'�tant pas modifi� par \idx\lowercase, le groupe semi-simple est donc bien referm� \emph{avant} d'effectuer la d�finition de \verb-#1-;
       \item on peut remarquer que l'argument \verb-#2- se trouve \emph{en dehors} de l'argument de \idx\lowercase car sinon, toutes les lettres majuscules de \verb|#2| seraient transform�es en minuscules.

       D'ailleurs, comme \verb-{#2}- est � la fin du texte de remplacement de la macro, il devient inutile de le lire puisqu'il sera lu juste apr�s. On peut optimiser la macro de cette fa�on\label{argument.def} :

       \centrecode-\def\defactive#1{%��*\defactive�
       \catcode`#1=13
       \begingroup
       \lccode`~=`#1
       \lowercase{\endgroup\def~}}-
\end{itemize}

Voyons cette macro � l'\oe uvre dans un exemple :

\showcode/\def\defactive#1{%��*\defactive�
       \catcode`#1=13
       \begingroup
       \lccode`~=`#1
       \lowercase{\endgroup\def~}%
}
\begingroup% les modifications restent locales�\idx*\begingroup�
       \defactive W{wagons}% d�finit le caract�re actif "W"��*\defactive�
       Les W constituent les trains.
\endgroup %fermeture du groupe, "W" redevient une lettre�\idx*\endgroup�
\par Les W sont des lettres/

\begin{exercice}
Supposons que �\verb-W-� soit rendu actif � l'aide de la macro �\defactive pour lui donner le texte de remplacement �wagons�. Imaginons ensuite que l'on rende �\verb|W|� non actif avec \idx\catcode\verb-`\W=11-.

\Qu estion : si l'on rend � nouveau \verb|W| actif, le texte de remplacement pr�c�demment d�fini existe-t-il encore ou faut-il red�finir son texte de remplacement ?
\solution
Il suffit de faire l'exp�rience :

\showcode/\defactive W{wagon}��*\defactive�
1) Les W constituent le train.\par
2) \catcode`W=11 Les W sont des lettres.\par�\idx*\catcode�
3) \catcode`\W=13 Les W constituent-ils le train ?/

La r�ponse est donc � oui �.

Le \idx[!caract�re actif]{texte de remplacement} d'un caract�re actif n'est pas perdu si ce caract�re change de catcode et redevient actif ensuite.
\end{exercice}

\begin{exercice}
D�crire ce qui va se passer si on d�finit le caract�re actif �\verb|W|� de la fa�on suivante :
\centrecode-\defactive W{Wagon}-

\solution
Tout d�pend de la version de �\defactive. La r�ponse est tr�s diff�rente selon que �\defactive lit 1 ou 2 arguments, c'est-�-dire si elle lit le texte de remplacement du caract�re actif ou pas.

Si elle le lit, le �\verb|W|� de �\verb|Wagon|� aura le catcode en vigueur au moment ou �\defactive lit son argument, c'est-�-dire 11\idx*{catcode!11 (lettre)}. Le texte de remplacement de �\verb|W|� sera �\verb|Wagon|� o� toutes les lettres ont le catcode 11.

\showcode|\def\defactive#1#2{%��*\defactive�
       \catcode`#1=13 % #1 sera actif apr�s la fin du texte de remplacement
       \begingroup
       \lccode`~=`#1  % dans \lowercase, changer les ~ (actifs) en "#1", ceux-ci �tant actifs
       \lowercase{\endgroup\def~}{#2}%
       }
\defactive W{Wagon}
Un W.|

Si �\defactive ne lit pas le texte de remplacement (version �optimis�e�), le caract�re �\verb|W|� sera actif � la fin du texte de remplacement et donc, lorsque \verb|\def W| lira le texte de remplacement entre accolades, le �\verb|W|� de �\verb|Wagon|� sera actif. On entrevoit ce qui va se passer lorsque \verb|W| sera ex�cut�. Dans un premier temps, \verb|W| va �tre remplac� dans la \idx{pile d'entr�e} par

\centrecode-Wagon-

puis le premier �\verb|W|�, actif, sera ex�cut� et donc, nous aurons dans la \idx{pile d'entr�e}

\centrecode-Wagonagon-

Le \verb|W| actif g�n�r� sera � nouveau ex�cut� et ainsi de suite\ldots{} Une \idx{boucle infinie} va s'amorcer au cours de laquelle les caract�res �\verb|agon|� seront ajout�s sur la \idx{pile d'entr�e} � chaque boucle, provoquant rapidement le d�passement de sa capacit� et g�n�rant le message d'erreur

\errcode|\def\defactive#1{%��*\defactive�
       \catcode`#1=13 % #1 sera actif apr�s la fin du texte de remplacement
       \begingroup
       \lccode`~=`#1 % dans \lowercase, changer les ~ (actifs) en "#1", ceux-ci �tant actifs
       \lowercase{\endgroup\def~}%
       }
\defactive W{Wagon}
Un W.|{\ttfamily ! TeX capacity exceeded, sorry [input stack size=5000]}

La morale que l'on peut retirer de cet exercice est qu'une � optimisation �, qui de prime abord peut sembler anodine (ne pas faire lire un argument par une macro), conduit � des limitations et � des erreurs de compilation qui n'existaient pas dans une version � non optimis�e �. La programmation en \TeX{} est pav�e d'embuches\ldots{} Il est donc n�cessaire de parfaitement savoir ce que l'on fait, de connaitre le r�gime de catcodes en cours lorsqu'une lecture est faite et toujours rester vigilant d�s lors qu'il est question de lecture d'argument.
\end{exercice}

Les man\oe uvres d�crites dans cette section reposent sur la supposition que �\cidx\~� est actif lorsque la macro �\defactive est \emph{d�finie}. Si ce n'est pas la cas et si, pour une raison ou pour une autre, �\cidx\~� a �t� neutralis� et mis dans la cat�gorie des caract�res � autres � de catcode 12\idx*{catcode!12 (autre)}, la macro �\defactive ne pourra et provoquera une erreur de compilation lors de son ex�cution.
\grandsaut

Tout ce qui a �t� dit avec les primitives \idx\lowercase et \idx\lccode est valable pour leurs sym�triques, les primitives \idx\uppercase et \idx\uccode qui agissent sur le � \idx{code majuscule} � d'un caract�re. On aurait d'ailleurs tout aussi bien pu proc�der avec \idx\uppercase et \idx\uccode.

\showcode|\def\defactive#1#2{%��*\defactive�
       \catcode`#1=13 % #1 sera actif apr�s la fin du texte de remplacement
       \begingroup
       \uccode`~=`#1 % dans \uppercase, changer les ~ (actifs) en "#1", ceux-ci �tant actifs�\idx*\uccode�
       \uppercase{\endgroup\def~}{#2}%�\idx*\uppercase�
}
\defactive W{Wagon}
Un W.|

Une macro � peu pr�s similaire �\letactive\verb|<token><token>| est facile � programmer :

\showcode|\def\letactive#1{%��*\letactive�
       \catcode`#1=13 % #1 sera actif apr�s la fin du texte de remplacement
       \begingroup
       \uccode`~=`#1 % dans \uppercase, changer les ~ (actifs) en "#1", ceux-ci �tant actifs�\idx*\uccode�
       \uppercase{\endgroup\let~}%�\idx*\uppercase�
}
\def\W{wagon}%
\letactive X\W��*\letactive�
Un X.|

\section{Afficher du code tel qu'il a �t� �crit}\label{litterate}\idx*[|(]{verbatim}
Le but est d'inventer une commande qui d�sactive toutes les r�gles de \TeX{} pour que son argument soit affich� tel qu'il a �t� �crit dans le code source, ce que l'on appelle du �verbatim�. Cette commande � �\litterate � va donc rendre inoffensifs tous les tokens de catcode autre que 11 ou 12, en changeant leur catcode pour 12. Ces tokens \emph{sp�ciaux} sont \boxtoken[]\textvisiblespace, \boxtoken[]\textbackslash, \boxtoken[]\{, \boxtoken[]\}, \boxtoken[]\$, \boxtoken[]\&, \boxtoken[]\#, \boxtoken[]{\char`\$}, \boxtoken[]\_, \boxtoken[]\% et \boxtoken[]{\char`\~}. Plain-\TeX{} d�finit\footnote{En plain-\TeX, les tokens \texttt{\string^\string^K} et  \texttt{\string^\string^A} sont des �quivalents pour �\texttt{\string^}� et �\texttt{\string_}�.} la macro \idx\dospecials de cette fa�on :

\indentcode[7em]-\def\dospecials{\do\ \do\\\do\{\do\}\do\$\do\&%
 \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~}-

La macro \idx\do peut �tre programm�e comme on l'entend pour agir sur son argument. Ici, comme le but est de changer le catcode de cet argument pour 12, on va donc la programmer ainsi :

\centrecode-\def\do#1{\catcode`#1=12 }-

\noindent et il suffira d'appeler \idx\dospecials pour qu'� partir de ce moment, tous les tokens sp�ciaux soient inoffensifs et deviennent affichables.

En ce qui concerne la syntaxe de �\litterate, il serait l�gitime d'�crire son argument entre accolades, mais cela rendrait la t�che compliqu�e. En effet, cette macro doit rendre tous les tokens sp�ciaux inoffensifs \emph{avant} de lire son argument. Par cons�quent, les accolades d�limitant l'argument ne seraient pas de \emph{vraies} accolades de catcode 1\idx*{catcode!1 (accolade)} et 2, mais des accolades de catcode 12\idx*{catcode!12 (autre)}. Pour savoir o� se situe la fin de l'argument, il faudrait parcourir le code qui se trouve apr�s �\litterate token par token, compter les accolades ouvrantes et fermantes jusqu'� obtenir l'�galit� entre ces deux quantit�s qui signifierait la fin de l'argument. C'est faisable, mais inutilement compliqu� et implique comme limitation que le code � afficher soit �quilibr� en accolades ouvrantes et fermantes. Le mieux est de d�cider � chaque fois d'un token (de catcode 11\idx*{catcode!11 (lettre)} ou 12\idx*{catcode!12 (autre)}) et de placer l'argument entre deux occurrences de ce token\footnote{C'est la syntaxe adopt�e par la macro \texttt{\string\verb} de \LaTeX.}. On peut par exemple �crire

\centrecode-\litterate|\foo # #34{ ~} &_\ |-

\noindent et obtenir l'affichage �\verb|\foo # #34{ ~} &_\ |�. La limitation �vidente est que le token choisi comme d�limiteur ne doit pas figurer dans l'argument.

Du c�t� de la programmation, la macro �\litterate doit ouvrir un groupe semi-simple puis rendre les tokens sp�ciaux inoffensifs. � l'aide de la macro �\defactive vue � la section pr�c�dente, elle doit aussi rendre actif le retour � la ligne �\verb-^^M-\verbidx*[ (retour charriot)]{^^M}� et lui donner comme texte de remplacement \idx\par\idx\leavevmode. Le \idx\leavevmode, en quittant le mode vertical\idx*{mode!vertical} mis en place par \idx\par{}, entre dans le mode horizontal\idx*{mode!horizontal} et commence un nouveau paragraphe. Sans ce \idx\leavevmode, deux retours � la ligne cons�cutifs seraient �quivalents � deux \idx[!cons�cutifs]\par et le second serait ignor� (voir r�gle page~\pageref{par.consecutifs}). De plus, le token fronti�re choisi doit aussi �tre rendu actif et pour devenir \idx\let-�gal � \idx\endgroup; ainsi, lorsque le second token fronti�re sera rencontr�, le groupe semi-simple sera ferm� et tous les catcodes seront restaur�s comme avant que la macro �\litterate n'entre en action.

\showcode|\def\litterate#1{% #1=lit le token fronti�re choisi��*\litterate�
       \begingroup% ouvre un groupe pour y faire les modifications�\idx*\begingroup�
               \def\do##1{\catcode`##1=12 }% \do change le catcode de son argument � 12�\idx*\do\idx*\catcode�
               \dospecials% rend inoffensifs tous les tokens sp�ciaux�\idx*\dospecials�
               \defactive\^^M{\leavevmode\par}% d�finit le retour charriot��*\defactive\idx*\leavevmode�
               \letactive#1\endgroup% d�finit #1 qui sera un \endgroup��*\letactive�
               \tt% passe en fonte � chasse fixe�\idx*\tt�
}
essai 1 : \litterate*\foo # #34{ �\%�} &_\ *
\medbreak�\idx*\medbreak�
essai 2 : \litterate/une premi�re ligne  ,, >>

un saut de ligne et la seconde --/|

L'ensemble fonctionne bien � part les espaces qui sont rendus avec le mauvais caract�re et les certaines \idx{ligature}s qui sont faites � l'essai \no2.

Pour l'espace tout d'abord, cela s'explique car son catcode a �t� rendu �gal � 12 par \idx\dospecials et le caract�re �\verb*| |� se trouve � la position de l'espace dans la \idx{fonte} � chasse fixe. Pour contourner ce probl�me, il faut rendre l'espace actif apr�s l'appel � \idx\dospecials et lui donner comme texte de remplacement la primitive \idx\ {}.

Ensuite, pour les \idx{ligature}s, il faut d�j� identifier quels sont les caract�res doubl�s qui forment une \idx{ligature} en fonte � chasse fixe. Ces caract�res sont : \boxtoken{`}, \boxtoken{<}, \boxtoken{>}, \boxtoken{,}, \boxtoken{'} et \boxtoken{-}. Pour �viter qu'ils ne forment une \idx{ligature}, il va falloir les rendre actifs et les faire suivre soit de �\verb|{}|�, soit de \idx\relax soit encore de \idx\kern\verb|0pt|, ou plus g�n�ralement de quelque chose ne se traduisant par aucun affichage. Ainsi, ils sembleront se suivre � l'affichage, mais aux yeux de \TeX{}, ils seront s�par�s par un n\oe ud\footnote{Un n\oe ud est un �l�ment, visible ou pas, qui entre dans la liste horizontale ou verticale que \TeX{} est en train de construire.} qui emp�chera la formation de la \idx{ligature}.

\showcode|\def\litterate#1{% #1=lit le token fronti�re choisi��*\litterate�
       \begingroup% ouvre un groupe pour y faire les modifications�\idx*\begingroup�
               \def\do##1{\catcode`##1=12 }% \do change le catcode de son argument � 12�\idx*\do\idx*\catcode�
               \dospecials% rend inoffensifs tous les tokens sp�ciaux�\idx*\dospecials�
               \defactive\^^M{\leavevmode\par}% d�finit le retour charriot�\idx*\leavevmode�*\defactive�
               \defactive\ {\ }% l'espace est actif et devient "\ "
               \defactive<{\string<{}}\defactive>{\string>{}}% emp�che�\idx*\string�
               \defactive-{\string-{}}\defactive`{\string`{}}% les
               \defactive,{\string,{}}\defactive'{\string'{}}% ligatures�\idx*{ligature}\idx*\string�*\defactive�
               \letactive#1\endgroup% #1 sera un \endgroup��*\letactive�
               \tt% passe en fonte � chasse fixe�\idx*\tt�
}
essai 1 : \litterate*\foo # #34{ %} &_\ *
\medbreak�\idx*\medbreak�
essai 2 : \litterate/une premi�re      ligne  ,, >>

un saut de ligne et la seconde --/��*\litterate�|\idx*[|)]{verbatim}

\chapter{Arguments d�limit�s}\idx*[|(]{argument!d�limit�}
\section{Th�orie}\label{theorie}
Les commandes que l'on d�finit avec \verb|\def| peuvent �galement avoir des �arguments d�limit�s�. Ces arguments-l� ne sont pas lus de la m�me fa�on que les arguments �non d�limit�s� que nous avons vus pr�c�demment. On indique � \TeX{} qu'une macro a un ou des arguments d�limit�s lorsque son \idx{texte de param�tre} contient d'autres unit�s lexicales que \verb-#-$i$ o� $i$ est un entier de 1 � 9. Ces unit�s lexicales sont appel�es les d�limiteurs.

\begin{regle}
Un argument \verb-#<-$i$\verb|>| est dit �d�limit� si, dans le \idx{texte de param�tre}, il est suivi par autre chose que \hbox{\verb-#<-$i$+1\verb|>|} ou que l'accolade �\cidx\{� qui marque le d�but du \idx{texte de remplacement}.
\end{regle}

Voici un exemple :
\centrecode-\def\foo.#1**#2#3/{Bonjour #1, #2 et #3}-

\noindent Ici, \verb-#1- et \verb-#3- sont les arguments d�limit�s puisqu'ils sont suivis par respectivement �\verb-**-� et �\verb-/-�. Par la suite, lorsque \TeX{} va ex�cuter \verb-\foo-, il s'attendra � ce qu'elle soit imm�diatement suivie de �\verb-.-� puis de quelque chose (qui sera l'argument \verb-#1-) qui s'�tendra jusqu'� la premi�re occurrence de �\verb-**-�, puis autre chose (qui deviendra les arguments \verb-#2#3-) qui s'�tendra jusqu'� la premi�re occurrence de �\verb-/-�. Ayant d�fini la commande  \verb-\foo- avec le code pr�c�dent, supposons que l'on �crive :
\centrecode-\foo.ab{123}c**xyz/-

\noindent Dans ce cas, \verb-#1- sera �\verb*-ab{123}c-�. \Qu ant aux tokens �xyz�, ils sont � r�partir entre \verb-#2- et \verb-#3- selon la r�gle suivante :

\begin{regle}
Lorsqu'une macro est ex�cut�e et qu'elle doit lire une suite de $n$ arguments dont le dernier est d�limit�, les $n-1$ premiers arguments sont assign�s comme des arguments non d�limit�s. Le dernier argument re�oit ce qui reste jusqu'au d�limiteur, ceci �tant �ventuellement vide.
\end{regle}

D'apr�s cette r�gle, l'argument \verb-#2- de l'exemple pr�c�dent n'est pas d�limit� et sera �\verb|x|�. L'argument \verb-#3- qui est d�limit� sera donc qu'il reste jusqu'au d�limiteur �\verb|/|� c'est-�-dire �\verb|yz|�. Le texte de remplacement sera donc :
\centrecode-Bonjour ab123c, x et yz.-

\begin{regle}
Dans tous les cas, qu'il soit d�limit� ou pas, si un argument est de la forme \verb-{<tokens>}-, o� \verb-<tokens>- est un ensemble d'unit�s lexicales o� les accolades sont �quilibr�es, alors \TeX{} \emph{supprime les accolades ext�rieures} et l'argument lu est �\verb-<tokens>-�.\idx*{argument!suppression d'accolades}
\end{regle}

Un cas particulier de cette r�gle engendre une autre r�gle :

\begin{regle}
Un argument d�limit� est vide si l'ensemble des tokens qui lui correspond est vide ou �\verb-{}-�.\idx*{argument!vide}%
\end{regle}

Ainsi, si on d�finit la macro \verb|\bar| ainsi :

\centrecode-\def\bar#1#2#3+{L'argument d�limit� est : "#3".}-

\noindent Alors, l'argument \verb|#3| est vide dans ces deux cas :
\begin{itemize}
       \item �\verb-\bar{123}x+-� car �\verb|123|� et �\verb|x|� sont les 2 premiers arguments et il ne reste rien pour le troisi�me;
       \item �\verb-\bar{a}{b}{}+-� car \verb|#3| re�oit �\verb|{}|�.
\end{itemize}
En revanche, si on avait �crit \verb-\bar{a}{b}{}{}+-, l'argument d�limit� aurait �t� �\verb-{}{}-� ce qui n'est pas un argument vide.
\grandsaut

Plut�t que d'envisager un par un de nombreux cas, voici un tableau qui affiche ce que seraient les arguments \verb-#1-, \verb-#2- et \verb-#3- dans plusieurs cas de figure avec la d�finition de \verb-\foo- rappel�e en haut du tableau :

\begin{centrage}
\small
\makeatletter
\def\fooa.#1**#2#3/{\textvide#1|}
\def\foob.#1**#2#3/{\textvide#2|}
\def\fooc.#1**#2#3/{\textvide#3|}
\def\textvide#1|{%
       \ifx_#1_<vide>%
       \else\ttfamily{\everyeof{\relax}\endlinechar\m@ne\catcode`\{=12 \catcode`\}=12 \catcode32=12 \scantokens{#1\relax}}%
       \fi}
\makeatother

\makeatother
\tabcolsep1em
\begin{tabular}{lccc}
\multicolumn4c{\ttfamily\string\def\string\foo.\#1**\#2\#3/\{...\}}\\[1ex]\hline
& \ttfamily\#1 & \ttfamily\#2 & \ttfamily\#3\\\hline
1. \verb*-\foo. abc**123/-& \fooa. abc**123/ & \foob. abc**123/ & \fooc. abc**123/\\
2. \verb*-\foo.**k/-&\fooa.**k/&\foob.**k/&\fooc.**k/\\
3. \verb*-\foo.1{**}2**{ab}{cd}/-&\fooa.1{**}2**{ab}{cd}e/&\foob.1{**}2**{ab}{cd}e/&\fooc.1{**}2**{ab}{cd}/\\
4. \verb*-\foo.{ab}**1{cd} /-&\fooa.{ab}**1{cd} /&\foob.{ab}**1{cd} /&\fooc.{ab}**1{cd} /\\
5. \verb*-\foo. **xy/-&\fooa. **xy/&\foob. **xy/&\fooc. **xy/\\
6. \verb*-\foo.xy** z/-&\fooa.xy** z/&\foob.xy** z/&\fooc.xy** z/\\
7. \verb*-\foo.xy** /-&\multicolumn3c{<Erreur de compilation>}\\
8. \verb*-\foo**/-&\multicolumn3c{<Erreur de compilation>}\\\hline
\end{tabular}
\end{centrage}
\noindent Voici maintenant quelques observations :
\begin{itemize}
       \item la ligne 1 met en �vidence que \verb-#1- r�colte ce qui est entre �\verb-.-� et �\verb-**-�, espaces compris ;
       \item on observe � la ligne 2 que le �\verb-.-� est imm�diatement suivi du d�limiteur �\verb-**-� et donc, l'argument d�limit� \verb-#1- est vide\idx*{argument!vide}. L'argument \verb-#3-, qui est d�limit�, est vide puisqu'il ne reste rien apr�s \verb-#2- qui est �k�;
       \item la ligne 3 montre que si le d�limiteur �\verb-**-� est entre accolades, il n'est pas reconnu comme d�limiteur et ne stoppe pas la lecture de l'argument \verb-#1-;
       \item � la ligne 4, l'argument d�limit� \verb-#1- est �\verb-{ab}-� et comme cet argument est un texte entre accolades, les accolades sont supprim�es lors de la lecture de cet argument\idx*{argument!suppression d'accolades}. Par contre, l'autre argument d�limit� \verb-#3- est �\verb*-{cd} -� et lui n'est pas r�duit � un texte entre accolades, il y a l'espace en plus. Les accolades ne sont donc pas supprim�es ;
       \item � la ligne 6, on peut se demander pour quelle raison \verb-#2- n'est pas �\verb*- -� et \verb-#3- n'est pas �\verb-z-�. En fait, l'argument non d�limit� \verb-#2- cherche son assignation dans �\verb*- z-� et comme on l'a vu au chapitre pr�c�dent, un espace est ignor� dans une liste d'arguments non d�limit�s\idx*{argument!espace}. Donc \verb-#2- devient �\verb-z-�, ce qui explique pourquoi l'argument d�limit� \verb-#3- est vide puisqu'il ne reste plus rien entre la fin de \verb-#2- et le d�limiteur �\verb|/|�
       \item l'erreur qui survient � la ligne 7 est due � l'argument non d�limit� \verb-#2- qui cherche son assignation dans �\verb*- /-�. Ignorant l'espace, \verb-#2- devient �\verb|/|� et capture le d�limiteur qui ne sera plus vu par \verb-\foo-. \TeX{} va donc lire du code jusqu'� ce qu'il rencontre une autre �\verb|/|�, ce qui est peu probable et qui, si cela arrivait, donnerait un argument \verb-#3- beaucoup plus �tendu que pr�vu. Si \TeX{} ne trouve pas d'autre �\verb|/|�, la lecture peut se poursuivre jusqu'� ce qu'il arrive sur un \idx\par et comme la macro n'est pas d�clar�e \idx\long, il va se plaindre d'un �{\ttfamily Paragraph ended before \verb-\foo- was complete}�\footnote{Le paragraphe s'est termin� avant que la lecture de \texttt{\string\foo} n'ait �t� achev�e.}. Si l'on est proche de la fin du fichier, \TeX{} peut m�me vainement chercher son d�limiteur �\verb|/|� jusqu'� la fin du fichier et �mettre un �{\ttfamily File ended while scanning use of \verb-\foo-}�\footnote{Fichier termin� pendant la lecture de \texttt{\string\foo}.}.
       \item � la ligne 8, ce qui suit la commande \verb-\foo- n'est pas �\verb-.-� donc \TeX{} nous informe que ce qu'il trouve ne correspond pas � ce qu'il attend avec un �\texttt{Use of \string\foo{} doesn't match its definition}�\footnote{L'emploi de {\ttfamily\string\foo} ne correspond  pas � sa d�finition.}.
\end{itemize}

\begin{exercice}
Voici une commande � arguments d�limit�s \verb-\bar-:
\centrecode-\def\bar#1#2:#3\relax#4{<code>}-

\begin{enumerate}
       \item \Qu els sont les arguments d�limit�s ?
       \item \Qu e valent les 4 arguments dans les cas suivants :
\begin{enumerate}
       \item \verb-\bar 123:456\relax789-
       \item \verb-\bar\def\relax:\relax\relax\relax-
       \item \verb-\bar:\relax:{\bar\relax}\bar\relax\bar-
       \item \verb-\bar0:a\relax-
\end{enumerate}
\item Donner un cas o� l'on est s�r d'obtenir une erreur de compilation.
\item Donner un cas o� \verb-#1- vaut �\verb-\bar12:34\relax5-� et \verb-#3- vaut �\verb-\relax-�.
\item Donner un cas o� \verb-#1- et \verb-#4- sont des arguments vides, mais pas \verb-#2- et \verb-#3-.
\end{enumerate}

\solution
Rappelons la d�finition de \verb-\bar- : \verb-\def\bar#1#2:#3\relax#4{<code>}-
\begin{enumerate}
       \item Les arguments d�limit�s sont le deuxi�me et le troisi�me. Il est important de noter que le 4\ieme{} n'est pas d�limit�.
       \item Voici les r�sultats pr�sent�s dans un tableau :
               \begin{centrage}\small
                       \begin{tabular}[t]{lcccc}\hline
                               & \verb-#1- & \verb-#2- & \verb-#3- & \verb-#4-\\\hline
                               a) & \verb-1- &\verb-23-&\verb-456-&\verb-7-\\
                               b) &\verb-\def- &\verb-\relax- &<vide> &\verb-\relax-\\
                               c) &\verb-:-&\verb-\relax- &\verb-{\bar\relax}\bar- &\verb-\bar-\\
                               d) &\verb-0-&<vide>&\verb-a-&<inconnu>\\\hline
                       \end{tabular}
               \end{centrage}
               Les  chiffres 8 et 9 au premier exemple et le dernier \idx\relax au deuxi�me exemple ne sont pas pris en compte par la macro \verb-\bar-.

               L'argument \verb-#4- de la derni�re ligne est qualifi� d'�inconnu�, car l'argument qui suit �\verb-\bar0:a\relax-� n'est pas pr�cis� dans l'�nonc�. Si cet argument est \idx\par ou deux retours � la ligne cons�cutifs (ce qui est la m�me chose), il y aura une erreur de compilation puisque dans ce cas, l'argument \verb-#4- serait ce \idx\par ce qui est interdit puisque la macro \verb-\bar- n'est pas d�clar�e \idx\long.
       \item Ce code �\verb-\bar:a\relax bcd\par-� provoquera une erreur de compilation, car l'argument \verb-#1- qui n'est pas d�limit� va capturer le �\verb-:-� qui ne sera plus visible par la macro \verb-\bar-. Celle-ci va donc poursuivre sa lecture jusqu'� trouver un autre �\verb-:-� pour affecter � l'argument d�limit� \verb-#2- ce qu'elle a emmagasin� jusque l�. Ce faisant, elle va tomber sur le \verb-\par- et comme cette macro  \verb-\bar- n'a pas �t� d�finie \idx\long, \TeX{} va �mettre une erreur de compilation.
       \item Par exemple �\verb-\bar{\bar12:34\relax5}X:{\relax}\relax Y-� o� ici les arguments 2 et 4 sont �\verb-X-� et �\verb-Y-�.
       \item Par exemple �\verb-\bar{}X:Y\relax{}-� o� les arguments 2 et 3 sont �\verb-X-� et �\verb-Y-�.
\end{enumerate}
\end{exercice}

\begin{exercice}
\Qu el sera l'affichage produit par le code suivant ?

\centrecode-\def\bar/#1#2/{*#1*#2*}
\bar////-

\solution
\TeX{} attend �\verb-/-� juste apr�s \verb-\bar-. Ce caract�re est donc absorb�. L'argument \verb-#1- n'est pas d�limit�, il re�oit donc le second �\verb-/-�. Comme \verb-#2- est un argument d�limit�, il sera vide puisque le second d�limiteur arrive imm�diatement apr�s \verb-#1-. Il reste le dernier �\verb-/-� qui n'a pas �t� lu avec la macro \verb-\bar- et ses arguments; il sera donc affich� tel quel juste apr�s la fin du texte de remplacement de \verb-\bar-.

On obtient donc : {\ttfamily\def\bar/#1#2/{*#1*#2*}\bar////}
\end{exercice}

\begin{exercice}
Soit une macro \verb-\baz- d�finie de cette fa�on : \verb-\def\baz#1\relax{#1}-. Elle ressemble un peu � la commande �\identity que nous avons d�j� vue � la page~\pageref{identity} sauf qu'ici, l'argument \verb-#1- est \emph{d�limit�}.

Lorsqu'elles sont ex�cut�es, expliquer s'il y a des diff�rences entre ces diff�rentes lignes de code et si oui, lesquelles :

\centrecode-\baz\let\bar=A\let\bidule=B\relax
\baz{\let\bar=A\let\bidule=B}\relax
\baz{\let\bar=A}{\let\bidule=B}\relax-
\solution
Pour la premi�re ligne, l'argument \verb-#1- est ce qui se trouve entre \verb-\baz- et \verb-\relax-, donc le texte de remplacement de ce code est �\verb-\let\bar=A\let\bidule=B-�. \TeX{} va donc d�finir deux lettres implicites.

� la deuxi�me ligne, \TeX{} lit l'argument �\verb-{\let\bar=A\let\bidule=B}-�. Comme il est r�duit � un texte entre accolades, ces accolades sont supprim�es\idx*{argument!suppression d'accolades} et donc cette ligne de code est strictement �quivalente � la premi�re.

Pour la troisi�me, l'argument est �\verb-{\let\bar=A}{\let\bidule=B}-� qui n'est pas r�duit � un texte entre accolades et ces accolades ne seront donc pas supprim�es lors de la lecture de l'argument. \TeX{} va donc d�finir des lettres implicites � l'int�rieur de deux groupes. Ces d�finitions seront perdues � la fin de chaque groupe, c'est-�-dire imm�diatement apr�s avoir �t� d�finies. Cette troisi�me ligne de code n'a donc aucun effet qui survit � la fermeture des deux groupes.
\end{exercice}

Le d�limiteur du dernier argument peut �galement �tre une accolade ouvrante. Lorsque la macro sera ex�cut�e, cela signifiera que \TeX{} s'attendra � ce que cet argument s'�tende jusqu'� la prochaine accolade ouvrante.

\begin{regle}
Pour sp�cifier que le dernier argument \verb|<i>| d'une macro doit �tre d�limit� par une accolade ouvrante, il faut �crire dans le \idx{texte de param�tre}

\centrecode-#<i>#{-

L'accolade qui suit le \cidx\# sert de d�limiteur et marque aussi le d�but du texte de remplacement.

Lorsque la macro sera ex�cut�e, l'argument \verb|#<i>| s'�tendra jusqu'� la prochaine accolade ouvrante\idx*{argument!d�limit�!par accolade}.
\end{regle}

Voici une macro \verb-\baz- o� son 3\ieme{} argument est d�limit� par une accolade ouvrante :

\showcode/\def\baz#1#2#3#{"#1", puis "#2" et enfin "#3".}
\baz{abc}def{gh}ij/

D'apr�s les r�gles vues dans ce chapitre, \verb|#1| est �\verb|abc|�, \verb|#2| est �\verb|d|� et l'argument d�limit� \verb-#3- est bien �\verb-ef-�. La suite du code, �\verb-{gh}ij-�, ne sera pas lu par la macro \verb-\baz-. C'est pourquoi l'affichage produit par ce code se trouve apr�s le point qui marque la fin de texte de remplacement de la macro \verb|\baz|.
\grandsaut

Voici enfin deux macros � usage �g�n�raliste� en programmation, toutes les deux � arguments d�limit�s. La premi�re �\firstto@nil lit tout ce qui se trouve jusqu'au prochain �\idx\@nil� et en prend le premier argument non d�limit�. La seconde, �\remainto@nil prend ce qui reste. Elles\footnote{Ces deux commandes sont \texttt{\string\@car} et \texttt{\string\@cdr} du noyau \LaTeX.} ne sont \emph{pas} � confondre avec �\firstoftwo et �\secondoftwo qui elles, ne sont pas � arguments d�limit�s\label{firstto@nil}.

On remarque que le caract�re  �\verb|@|�\idx*{"@ (nom de macros priv�es)} fait partie du nom de ces deux macros ainsi que de \idx\@nil, ce qui est normalement interdit. Pour que cela soit possible, il faut modifier le code de cat�gorie de l'arobase qui est naturellement 12 pour le mettre � 11, celui des lettres, afin qu'il puisse servir � constituer un nom de macro. En \TeX{}, on doit �crire �\texttt{\string\catcode`\string\@=11}� pour que \verb|@| devienne une lettre puis �\texttt{\string\catcode`\string\@=12}� pour revenir au r�gime de catcode de l'arobase par d�faut. En \LaTeX{}, les macros \idx\makeatletter et \idx\makeatother effectuent ces actions.

La zone de ces modifications sera limit�e aux d�finitions des macros de telle sorte qu'il ne sera plus possible de se r�f�rer � ces macros par la suite. L'int�r�t est qu'elles deviennent � priv�es �, terme qu'il faut comprendre au sens de � envers du d�cor r�serv� � un usage de programmation �, ou encore � � ne pas mettre entre toutes les mains �. Ainsi, l'utilisateur final ne peut pas y acc�der, sauf �videmment s'il effectue la man\oe uvre de modification du catcode de \verb|@|\footnote{\LaTeX3 utilise le caract�re �\texttt{\string_}� pour ses macros priv�es.}.

Voici les d�finitions et quelques exemples d'utilisation de �\firstto@nil et �\remainto@nil :

\showcode/\catcode`\@11
\long\def\firstto@nil#1#2\@nil{#1}��*\firstto@nil�
\long\def\remainto@nil#1#2\@nil{#2}��*\remainto@nil�
a) \firstto@nil foobar\@nil   \qquad b) \remainto@nil foobar\@nil  \par�\idx*\qquad�
c) \firstto@nil {foo}bar\@nil \qquad d) \remainto@nil {foo}bar\@nil��*\firstto@nil�*\remainto@nil�/

On voit souvent cette macro \idx\@nil dans le code de \LaTeX{} et on la verra aussi fr�quemment dans les macros de ce livre. On peut se demander ce qu'elle fait vraiment et quelle est sa d�finition. La r�ponse est tr�s simple : il est admis que \idx\@nil est une macro \emph{non d�finie} (et doit le rester) dont le seul usage est de servir de d�limiteur pour argument d�limit�. Ici, une pr�cision s'impose : le fait qu'elle ne soit pas d�finie \emph{n'implique pas} que, en tant que d�limiteur, elle soit interchangeable avec une autre macro non d�finie.

\begin{regle}
Lorsqu'un d�limiteur d'argument est une \idx{s�quence de contr�le}, \TeX{} ne prend pas en compte la signification de cette \idx{s�quence de contr�le} : seuls les caract�res qui composent son nom sont examin�s.
\end{regle}

Si par exemple, on d�finit une macro \verb|\foo| ainsi :

\centrecode-\def\foo#1\truc{<code>}-

\noindent alors par la suite, \TeX{} s'attendra � ce que \verb|\foo| soit suivie d'un code (qui deviendra l'argument \verb|#1|) dont la fin sera marqu�e par \verb|\truc| (c'est-�-dire le caract�re d'�chappement suivi des lettres \verb|t|, \verb|r|, \verb|u| et \verb|c|). M�me si une autre macro \verb|\machin| est rendue \idx\let-�gale � \verb|\truc|, cette macro \verb|\machin| ne sera pas comprise comme le d�limiteur de la macro \verb|\foo|.

\begin{exercice}
Existe-t-il une diff�rence de comportement entre ces deux lignes de code et si oui, laquelle :

\centrecode-\firstoftwo{<code1>}{<code2>}��*\firstoftwo�
\firstto@nil{<code1>}{<code2>}\@nil��*\firstto@nil�-

\solution
Il n'y a pas de diff�rence de comportement. Ces deux lignes se comportent de fa�on identique. Dans les deux cas, l'argument \verb-#1- n'est pas d�limit� et va �tre d�pouill� de ses accolades\idx*{argument!suppression d'accolades}. Leur texte de remplacement est donc pour toutes les deux : \verb-<code1>-. De plus, elles ont toutes les deux lu et absorb� l'argument \verb-<code2>- qui disparait dans leur texte de remplacement.

Cette �quivalence serait �galement valable entre ces 3 lignes qui toutes ex�cutent \verb|<code2>|:

\centrecode-\secondoftwo{<code1>}{<code2>}��*\secondoftwo�
\remainto@nil{<code1>}{<code2>}\@nil��*\remainto@nil�
\remainto@nil{<code1>}<code2>\@nil��*\remainto@nil�-
\end{exercice}

\section{Mise en pratique}
Les arguments d�limit�s ne pr�sentent pas de difficult� th�orique sp�ciale, aussi il est temps de les utiliser sur un exemple.

\subsection{Afficher ce qui est � droite d'un motif}\label{rightof}
Nous allons nous employer � programmer une macro�\rightof[|(] dont la syntaxe est

\centrecode-\rightof{<chaine>}{<motif>}-

\noindent et qui affiche ce qui est � gauche du \verb|<motif>| dans la \verb|<chaine>|, �tant entendu que si \verb|<motif>| ne figure pas dans la \verb|<chaine>|, rien ne doit �tre affich�.

Du c�t� de la m�canique interne, cette macro se contentera de lire ses deux arguments, de d�finir et d'appeler une macro \verb|\right@of|. Cette macro, � arguments d�limit�s, sera charg�e d'effectuer le travail.

L'int�r�t du �\verb|@|� dans �\verb|\right@of| est de marquer la fronti�re entre macro publique et macro priv�e pour d�limiter ce qui a une syntaxe clairement d�finie et stable dans le temps pour les macros publiques de ce qui est de la cuisine interne pour les macros priv�es. Ces derni�res sont susceptibles d'�tre modifi�es, voire supprim�es pourvu que la syntaxe et les fonctionnalit�s de la macro publique soient conserv�es.
\grandsaut

Voici comment doit �tre d�finie la macro \verb|\right@of|:

\centrecode-\def\rightof#1<motif>#2\@nil{#2}-

\noindent o� le d�limiteur \verb|<motif>| est l'argument \verb|#2| de la macro principale.

Voici donc le code de \verb|\rightof| o�, conform�ment � ce qui a �t� dit, les tokens de param�tre \verb|#| sont doubl�s pour la macro �fille� \verb|\right@of| :

\showcode/\catcode`\@=11 % "@" devient une lettre
\def\rightof#1#2{%��*\rightof�
       \def\right@of##1#2##2\@nil{##2}% d�finit la macro auxiliaire
       \right@of#1\@nil% appelle la macro auxiliaire o� #1 est la <chaine>
}
\catcode`\@=12 %"@" redevient un signe�\idx*\catcode�
--\rightof{Programmation}{g}--\par�\defline\aaa�
--\rightof{Programmation}{gram}--\par
--\rightof{Programmation}{on}--/

\subsection{Les cas probl�matiques}
La macro fonctionne bien\ldots{} En apparence seulement, car le cas o� \verb|<chaine>| ne contient pas le \verb|<motif>| n'a pas encore �t� examin� :

\errcode/\catcode`\@=11 % "@" devient une lettre
\def\rightof#1#2{%
       \def\right@of##1#2##2\@nil{##2}% d�finit la macro auxiliaire
       \right@of#1\@nil% appelle la macro auxiliaire
}
\catcode`\@=12 %"@" redevient un signe
--\rightof{Programmation}{z}--\par
--\rightof{Programmation}{Gram}/{! Paragraph ended before \string\right@of was complete. <to be read again>}

\TeX{} explique qu'un \idx\par a �t� rencontr� avant que l'argument ne soit enti�rement lu, ce qui est interdit puisque la macro n'est pas d�clar�e \idx\long. Le texte de remplacement de \verb-\rightof{Programmation}{z}- (cas de la ligne \no\aaa) permet d'analyser ce qui se passe. Le texte de remplacement est �crit ci-dessous (les doubles \verb-##- ont �t� remplac�s par des simples puisque nous �crivons le texte de remplacement) :

\centrecode-\def\right@of#1z#2\@nil{#2}
\entre@ Programmation\@nil-

\noindent La premi�re ligne sp�cifie donc que la macro \verb-\right@of- doit �tre suivie de quelque chose (l'argument \verb-#1-) qui s'�tend jusqu'� �\verb|z|� puis de quelque chose (l'argument \verb-#2-) qui s'�tend jusqu'au \idx\@nil. Or, �\verb|z|� ne figure pas entre \verb|\right@of| et \idx\@nil puisque ce qui s'y trouve est l'argument \verb|#1| de la macro \verb|rightof|, c'est-�-dire � Programmation� ! C'est pourquoi \TeX{} le cherche jusqu'� tomber sur le \idx\par qui stoppe cette vaine recherche puisque la macro n'est pas d�clar�e \idx\long.

Tout serait bien plus facile si on disposait d'une macro qui teste si le \verb|<motif>| est contenu dans \verb|<chaine>| : dans l'affirmative, il suffirait d'appeler la macro \verb|\right@of| pr�c�demment d�finie et sinon, ne rien faire ce qui revient � ne rien afficher. Une telle macro, capable de faire un test, sera �crite plus tard (voir page~\pageref{ifin}). En attendant, il faut trouver une astuce pour se prot�ger de cet inconv�nient.

En fait aucune erreur ne serait �mise si, quelle que soit la \verb|<chaine>|, \verb|\right@of| voyait toujours le \verb|<motif>| avant le \idx\@nil. Afin qu'il en soit ainsi, on va d�lib�r�ment �crire ce \verb|<motif>| quelque part entre \verb|\right@of| et \idx\@nil lors de l'appel � la macro \verb|\right@of|. L'�crire juste avant le \idx\@nil nous assure que rien ne sera renvoy� dans le cas o� \verb|<chaine>| ne contient pas \verb|<motif>| puisque dans ce cas, \verb|##2| est vide :

\showcode/\catcode`\@=11 % "@" devient une lettre
\def\rightof#1#2{%��*\rightof�
       \def\right@of##1#2##2\@nil{##2}% d�finit la macro auxiliaire�\defline\aaa�
       \right@of#1#2\@nil% appelle la macro auxiliaire avec le motif #2�\defline\bbb�
}
\catcode`\@=12 %"@" redevient un signe
--\rightof{Programmation}{g}--\par
--\rightof{Programmation}{ti}--\par
--\rightof{Programmation}{z}--\par
--\rightof{Programmation}{Gram}--/

L'inconv�nient qui saute aux yeux est que le motif \verb|#2|, ajout� juste avant \idx\@nil, est dirig� vers l'affichage lorsque la \verb|<chaine>| contient le \verb|<motif>| ! Tout simplement parce que l'argument \verb|##2| de \verb|\right@of| qui est affich� est ce qui se trouve entre la \emph{premi�re} occurrence du \verb|<motif>| et \idx\@nil.

Pour mieux comprendre ce qui se joue en coulisses, examinons ce qui se passe lorsque l'appel �\verb|\rightof{Programmation}{g}|� est ex�cut� :

\begin{enumerate}
       \item la macro \verb|\right@of| est d�finie par : \verb|\def\right@if#1g#2\@nil{#2}| � la ligne \no\aaa;
       \item �crire �\verb|\right@of Programmationg\@nil|� donne ce qui se trouve entre la premi�re occurrence de �\verb|g|� et \idx\@nil, c'est donc �\verb|rammationg|� qui est affich�.
\end{enumerate}

Proc�dons de m�me avec l'appel �\verb|\rightof{Programmation}{z}|�, cas o� le \verb|<motif>| n'est pas contenu dans la \verb|<chaine>| :

\begin{enumerate}
       \item la macro \verb|\right@of| est d�finie par : \verb|\def\right@if#1z#2\@nil{#2}|;
       \item �crire �\verb|\right@of Programmationz\@nil|� donne ce qui se trouve entre �\verb|z|� et \idx\@nil, c'est-�-dire rien.
\end{enumerate}

Comment faire en sorte que le \verb|<motif>| rajout� juste avant le \idx\@nil ne soit pas affich� dans le cas o� \verb|<motif>| est contenu dans \verb|<chaine>| ? R�ponse : en incluant dans l'argument \verb|##2| de \verb|\right@of| une autre macro � argument d�limit�e qui fera disparaitre ce qui est ind�sirable. Cette macro � argument d�limit� sera �\gobto@@nil et absorbera tout ce qui se trouve entre elle et le prochain \verb|\@@nil| rencontr�. On note ici qu'il ne s'agit pas de \idx[|etc]\@nil mais de \verb|\@@nil| afin que le d�limiteur de cette macro lui soit sp�cifique :

\centrecode-\def\gobto@@nil#1\@@nil{}-

On va donc ajouter un \verb|\@@nil| lors de l'appel � la macro \verb|\right@of| :

\centrecode-\right@of#1#2\@@nil\@nil-

\noindent Et il nous reste � correctement placer la macro �\gobto@@nil. Pour que ce \verb|\@@nil| soit toujours appari� avec une macro �\gobto@@nil, que \verb|<motif>| soit contenu dans \verb|chaine| ou pas, il faut mettre �\gobto@@nil juste avant et juste apr�s \verb|#2| :

\showcode/\catcode`\@=11 % "@" devient une lettre
\def\gobto@@nil#1\@@nil{}��*\gobto@@nil�
\def\rightof#1#2{%
       \def\right@of##1#2##2\@nil{##2}% d�finit la macro auxiliaire
       \right@of#1\gobto@@nil#2\gobto@@nil\@@nil\@nil% appelle la macro auxiliaire��*\gobto@@nil�
}
\catcode`\@=12 %"@" redevient un signe
--\rightof{Programmation}{g}--\par��*\rightof�
--\rightof{Programmation}{ti}--\par
--\rightof{Programmation}{z}--\par
--\rightof{Programmation}{Gram}--/

Faisons fonctionner la macro �\rightof dans le cas o� \verb|<motif>| est contenu dans \verb|<chaine>|. Comme pr�c�demment, examinons quels sont ses arguments lorsque l'on �crit �\verb|\rightof{Programmation}{g}|�:

\begin{enumerate}
       \item l'appel � la macro \verb|\right@of| se fait ainsi :

       \centrecode-\right@of Programmation\gobto@@nil g\gobto@@nil\@@nil\@nil-�*\gobto@@nil
       \item son argument \verb|#2|, qui est entre le premier �\verb|g|� et \verb|\@nil| est :

       \centrecode-rammation\gobto@@nil g\gobto@@nil\@@nil-
       \item l'affichage qui en r�sulte est bien �rammation� car la macro �\gobto@@nil absorbe tout ce qui se trouve jusqu'au \verb|\@@nil|. \TeX{} ne tient aucun compte de ce qu'il absorbe. \Qu e la macro �\gobto@@nil y figure ou pas n'y change rien : la macro � argument d�limit� effectue � b�tement � son travail sans analyser ce qui se trouve dans son argument.
\end{enumerate}

Voici maintenant le cas o� \verb|<motif>| n'est contenu dans \verb|<chaine>|, comme lorsqu'on �crit �\verb|\rightof{Programmation}{z}|� :

\begin{enumerate}
       \item la macro \verb|\right@of| est appel�e par

       \centrecode-\right@of Programmation\gobto@@nil z\gobto@@nil\@@nil\@nil-
       \item l'argument \verb|#2| se trouve entre le �\verb|z|� et le \verb|\@nil| :

       \centrecode-\gobto@@nil\@@nil-
       \item gr�ce � la d�finition de �\gobto@@nil, ce code ne se traduit par aucun affichage.
\end{enumerate}

Impliquer ainsi plusieurs macros � arguments d�limit�s et faire en sorte que la suivante h�rite de l'argument de la pr�c�dente pour le traiter � son tour est couramment utilis� en programmation et d�montre, comme dans ce cas particulier, la puissance des arguments d�limit�s. En revanche, la gymnastique mentale requise pour  mettre en place un tel dispositif et correctement envisager tous les cas est loin d'�tre naturelle et demande une certaine habitude\ldots{} Le plus difficile est d'analyser un code d�j� �crit, voire de comprendre un code que l'on avait �crit soi-m�me et oubli� entre temps. \Qu i peut se vanter de comprendre du premier coup d'\oe il l'appel � la macro auxiliaire mise au point pr�c�demment ?

\centrecode-\right@of#1\gobto@@nil#2\gobto@@nil\@@nil\@nil-�*\gobto@@nil

Le manque de lisibilit� est criant et d�montre l'importance de commenter son code, autant pour soi-m�me que pour les autres. Pour augmenter la lisibilit� du code, il serait pr�f�rable de recourir � une macro \verb|\ifin| (dont l'�laboration sera expliqu�e page~\pageref{ifin}) qui teste si l'argument \verb|#1| contient l'argument \verb|#2| et ayant pour syntaxe

\centrecode-\ifin{#1}{#2}
       {<code � ex�cuter si vrai>}
       {<code � ex�cuter si faux>}%-

\noindent On peut ainsi programmer plus confortablement et utiliser la toute premi�re version de \verb|\rightof| et se dispenser d'envisager le cas probl�matique o� \verb|<chaine>| ne contient pas le \verb|<motif>| :

\showcode/\catcode`\@=11 % "@" devient une lettre
�\string\def\string\if{}in\#1\#2\#3\#4\string{<\textit{code vu plus tard}\string}>�
\def\rightof#1#2{%��*\rightof�
       \ifin{#1}{#2}%
               {% si #1 contient le #2
               \def\right@of##1#2##2\@nil{##2}% d�finit la macro auxiliaire
               \right@of#1\@nil% appelle la macro auxiliaire
               }%
               {}% sinon, ne rien faire
}
\catcode`\@=12 %"@" redevient un signe�\idx*\catcode�
--\rightof{Programmation}{g}--\par
--\rightof{Programmation}{z}--\par
--\rightof{Programmation}{o}--/

\subsection{� gauche toute}\label{leftof}
Ne nous arr�tons pas en si bon chemin et venons-en � la macro sym�trique de �\rightof, la macro �\leftof[|(] qui sera charg�e d'afficher ce qui est � gauche du \verb|<motif>| dans la \verb|<chaine>|.

Pour se pr�munir de l'erreur de compilation rencontr�e dans le cas o� le \verb|<motif>| (argument \verb|#2|) n'est pas contenu dans la \verb|<chaine>| (argument \verb|#1|), proc�dons comme avec �\rightof et ajoutons ce \verb|<motif>| lors de l'appel � la macro auxiliaire :

\showcode/\catcode`\@=11
\def\leftof#1#2{%��*\leftof�
       \def\leftof@i##1#2##2\@nil{##1}% renvoie ce qui est � gauche de #2
       \leftof@i #1#2\@nil% ajoute #2 apr�s #1
}
\catcode`\@=12
--\leftof{Programmation}{ram}--\par
--\leftof{Programmation}{zut}--��*\leftof�/

Cela �tait attendu : lorsqu'on �crit \verb|\leftof@i #1#2\@nil|, si \verb|#1| ne contient pas \verb|#2|, alors le \verb|#2| ajout� en fin d'argument devient la premi�re occurrence du \verb|<motif>| et donc, \verb|#1| est affich� en entier.

� nouveau, il va falloir d�ployer une m�thode astucieuse pour que, lorsque \verb|#1| est renvoy� en entier (ce qui correspond au cas probl�matique), rien ne soit affich�. Pour cela, la macro auxiliaire \verb|\leftof@i| ne va pas afficher, \verb|##1| mais transmettre ce �\verb|##1#1|� � une autre macro auxiliaire \verb|\leftof@ii|. Cette derni�re aura comme d�limiteur d'argument est \verb|#1| tout entier et se chargera d'afficher ce qui est � gauche de la \verb|<chaine>| \verb|#1| :

\centrecode-\def\leftof@ii##1#1##2\@nil{##1}-

Ainsi, la macro \verb|\leftof@i| devient :

\centrecode-\leftof@i##1#2##2\@nil{\leftof@ii##1#1\@nil}-

\noindent et on ajoute ici aussi \verb|#1| apr�s \verb|##1| pour que la macro \verb|\leftof@ii| voie toujours la \verb|<chaine>| \verb|#1| :

\showcode/\catcode`\@=11
\def\leftof#1#2{%��*\leftof�
       \def\leftof@i##1#2##2\@nil{\leftof@ii##1#1\@nil}%
       \def\leftof@ii##1#1##2\@nil{##1}%
       \leftof@i #1#2\@nil
}
\catcode`\@=12 �\idx*\catcode�
--\leftof{Programmation}{ram}--\par
--\leftof{Programmation}{zut}--/

Compte tenu de la faible lisibilit� de ce code et de la difficult� � suivre comment se transmettent les arguments, voici un tableau montrant comment sont lus et isol�s les arguments d�limit�s dans le cas o� \verb|<chaine>| contient \verb|<motif>|, c'est-�-dire le premier cas. On a encadr� ce qui d�limite les arguments des macros :

\begin{centrage}
       \footnotesize
       \frboxsep=0.5pt
       \def\mystrut{\vphantom{\normalfont Programmation}}
       \begin{tabular}{|r|c|}\hline
               Appel macro principale & \verb|\leftof{Programmation}{ram}|\\\hline
               Appel � \verb|\leftof@i|& \frbox{\ttfamily\mystrut\string\leftof@i}Prog\frbox{\mystrut ram}mationram\verb|\@nil|\\
               Argument \verb|##1| retenu par \verb|\leftof@i| & Prog\\\hline
               Appel � \verb|\leftof@ii|& \frbox{\ttfamily\mystrut\string\leftof@ii}Prog\frbox{\mystrut Programmation}\verb|\@nil|\\
               Argument \verb|##1| retenu par \verb|\leftof@ii| &\ttfamily Prog\\\hline
               Affichage & Prog\\\hline
       \end{tabular}
\end{centrage}

Voici maintenant le d�roulement des op�rations lorsque \verb|<chaine>| ne contient pas \verb|<motif>| :

\begin{centrage}
       \footnotesize
       \frboxsep=0.5pt
       \def\mystrut{\vphantom{\normalfont Programmation}}
       \begin{tabular}{|r|c|}\hline
               Appel macro principale & \verb|\leftof{Programmation}{zut}|\\\hline
               Appel � \verb|\leftof@i|& \frbox{\ttfamily\mystrut\string\leftof@i}Programmation\frbox{\mystrut zut}\verb|\@nil|\\
               Argument \verb|##1| retenu par \verb|\leftof@i| & Programmation\\\hline
               Appel � \verb|\leftof@ii|& \frbox{\ttfamily\mystrut\string\leftof@ii}\kern.5pt \frbox{\mystrut Programmation}Programmation\verb|\@nil|\\
               Argument \verb|##1| retenu par \verb|\leftof@ii| &\ttfamily <vide>\\\hline
               Affichage & \ttfamily <vide>\\\hline
       \end{tabular}
\end{centrage}

Il est bon de noter que la macro �\leftof, bien que requ�rant elle aussi deux macros auxiliaires, est programm� diff�remment de \verb|\rightof|. Dans le cas de �\leftof, la deuxi�me macro auxiliaire \verb|\leftof@ii| est appel�e \emph{dans l'argument} de \verb|\leftof@i|. Dans le cas de \verb|\rightof|, la deuxi�me macro auxiliaire �\gobto@@nil �tait �crite dans l'appel � la macro \verb|\right@of|, ce qui est un cas particulier pas toujours faisable.

\begin{exercice}
Modifier la macro �\rightof pour utiliser la m�thode employ�e avec �\leftof : la premi�re macro auxiliaire \verb|\rightof@i| appellera \emph{dans son argument} une deuxi�me macro auxiliaire \verb|\rightof@ii|.

\solution
On utilise une astuce similaire � celle vue avec �\leftof : la deuxi�me macro auxiliaire \verb|\rightof@ii| va renvoyer ce qui est � \emph{gauche} du \verb|<motif>| puisque celui-ci, ind�sirable, �tait rajout� � la toute fin de l'appel � \verb|\rightof@i| :

\showcode/\catcode`\@=11
\def\rightof#1#2{%��*\rightof�
       \def\rightof@i##1#2##2\@nil{\rightof@ii##2#2\@nil}%
       \def\rightof@ii##1#2##2\@nil{##1}%
       \rightof@i#1#2\@nil
}
\catcode`\@=12 �\idx*\catcode�
--\rightof{Programmation}{g}--\par
--\rightof{Programmation}{z}--/

Il est int�ressant de noter que lorsque le \verb|<motif>| est �\verb|z|�, l'argument \verb|##2| de \verb|\rightof@i| est vide et donc, l'argument \verb|##1| de \verb|\rightof@ii| est vide aussi.
\end{exercice}�*\leftof[|)]

\subsection{Autre probl�me : les accolades dans le motif}\label{rightof.et.accolades}
On n'en a pas fini avec les cas probl�matiques\ldots{} Examinons maintenant pourquoi la macro \verb-\rightof- ne fonctionne pas lorsqu'elle est appel�e avec un argument \verb|#2| contenant un (ou des) groupe(s) entre accolades. Voici un exemple simple o� une erreur de compilation est produite :

\errcode/\catcode`\@=11
\def\gobto@@nil#1\@@nil{}��*\gobto@@nil�
\def\rightof#1#2{%
       \def\right@of##1#2##2\@nil{##2}% d�finit la macro auxiliaire
       \right@of#1\gobto@@nil#2\gobto@@nil\@@nil\@nil% appelle la macro auxiliaire��*\gobto@@nil�
}
\catcode`\@=12
\rightof{abc{1}def}{c{1}d}% affiche ce qui est � droite de "c{1}d"/{You can't use `macro parameter character \string##' in horizontal mode.}

\noindent Pour comprendre ce qu'il se passe avec le token �\verb-#-� qui est incrimin� dans le message d'erreur, �crivons le texte de remplacement de \verb|\rightof{abc{1}def}{c{1}d}| :

\centrecode/\def\right@of##1c{1}d##2\@nil{##2}
\right@of abc{1}def\gobto@@nil c{1}d\gobto@@nil\@@nil\@nil��*\gobto@@nil�/

Le probl�me se trouve � la premi�re ligne. \TeX{} va lire �\verb-\def\right@of##1c{1}-� ce qui va d�finir la macro auxiliaire \verb-\rightof@- : elle sera donc � argument d�limit� par �\verb|c|� et son texte de remplacement sera �\verb|1|�. Par la suite, les tokens qui restent � lire sont �\verb-d##2\@nil{##2}-�. Ceux-ci n'�tant plus dans le \idx{texte de param�tre} d'une macro, \TeX{} bute �\verb-#-�, car ce token est justement attendu dans le texte de param�tre d'une macro\footnote{On le rencontre aussi dans le pr�ambule d'un alignement initi� par la primitive \texttt{\string\halign} ou \texttt{\string\valign}.}. Le message d'erreur signale donc que \TeX{} rencontre ce token dans un contexte (ici, le mode horizontal\idx*{mode!horizontal}) dans lequel il est interdit. D'ailleurs, si le mode en cours avait �t� le mode vertical\idx*{mode!vertical}, le message aurait �t� le m�me : �\texttt{You can't use `macro parameter character \#' in vertical mode.}�

Il est difficile de modifier la macro �\rightof[|)] pour qu'elle puisse aussi trouver ce qui est entre deux arguments qui comportent des groupes entre accolades, car dans ces cas, les arguments d�limit�s sont interdits. Nous emploierons une tout autre m�thode, bien plus lente, qui consisterait � s'y prendre token par token (voir page~\pageref{parser.code}).

\begin{regle}
Les d�limiteurs figurant dans le \idx{texte de param�tre} d'une macro ne peuvent pas contenir de tokens de catcode 1\idx*{catcode!1 (accolade)} ou 2 �quilibr�s (accolade ouvrante et fermante) car celles-ci seraient interpr�t�es non pas comme faisant partie d'un d�limiteur, mais comme marquant les fronti�res du texte de remplacement.\medskip

La cons�quence est donc que lorsqu'une macro d�finit une \idx{macro fille} � argument d�limit� o� les d�limiteurs sont les arguments de la macro m�re, ceux-ci ne peuvent pas contenir un groupe entre accolades.
\end{regle}\idx*[|)]{argument!d�limit�}

\chapter{D�veloppement}\idx*[|(]{d�veloppement}
\TeX{} est un langage particulier et parmi d'autres subtilit�s, le d�veloppement est un de ses m�canismes intimes. Maitriser le d�veloppement est n�cessaire pour programmer, car cette notion occupe une place centrale dans la programmation \TeX. Certains diraient que la gestion du d�veloppement fait partie des choses assez p�nibles, mais lorsqu'on programme, il est souvent n�cessaire de savoir contr�ler finement ce m�canisme fondamental. Ce chapitre, consacr� � l'apprentissage des outils permettant de contr�ler le d�veloppement, nous ouvrira la voie pour appr�hender la programmation abord�e dans les parties suivantes.

\section{D�veloppement des commandes}
Int�ressons-nous aux commandes (qui ont un texte de remplacement donc), par opposition aux \idx{primitive}s qui sont � cod�es en dur � dans \TeX{}. Le texte de remplacement est, en quelque sorte, la d�finition de la commande, c'est-�-dire la repr�sentation interne qu'en a \TeX{}. Reprenons par exemple la commande tr�s simple \verb-\foo- d�finie par :

\centrecode-\def\foo{Bonjour}-

\noindent Son texte de remplacement est � Bonjour �, c'est-�-dire que dans le code, lorsque \TeX{} va rencontrer \verb-\foo-, alors il va aller chercher sa signification dans sa m�moire et va remplacer cette \idx{s�quence de contr�le} par son texte de remplacement qui est � Bonjour �. Ce remplacement, cette substitution, cette transformation du code s'appelle le � d�veloppement �, et on dit que la macro \verb-\foo- a �t� d�velopp�e par \TeX{}. Pour �tre tout � fait clair, cette � transformation du code �, a lieu dans la m�moire de \TeX{} (nomm�e � \idx{pile d'entr�e} �). Le code source n'est bien �videmment pas modifi�.

\begin{regle}[R�gle et d�finition]
\TeX{} est un langage de macros, c'est-�-dire qu'il agit comme un outil qui \emph{remplace} du code par du code. Ce remplacement, aussi appel� d�veloppement, a lieu dans une zone de m�moire nomm�e \og \idx{pile d'entr�e}\fg.

Ainsi, lorsque \TeX{} ex�cute une macro, elle (ainsi que ses �ventuels arguments) est d'abord remplac�e par le code qui lui a �t� donn� lorsqu'on l'a d�finie avec \verb|\def|. Ce code est le \og \idx{texte de remplacement}\fg{}. Une fois que ce d�veloppement a �t� fait, \TeX{} continue sa route en tenant compte du remplacement effectu�.
\end{regle}

Prenons le temps d'examiner en d�tail ce qui se passe r�ellement et d�finissons les conventions suivantes : le symbole \TeXhead{} repr�sente l'endroit o� \TeX{} s'appr�te � lire la suite du code. On a vu qu'il ne lisait que ce dont il avait besoin, et on va donc encadrer en pointill�s le ou les tokens que \TeX{} va lire � la prochaine �tape. Lorsque le d�veloppement se fait, la pile est encadr�e. Observons donc, �tape par �tape ce qui se passe lorsqu'on �crit �\verb-\foo le monde-� (l'espace apr�s \verb-\foo- sera ignor� en vertu de la r�gle concernant les espaces du code vue � la page~\pageref{regle.espace}) :\smallbreak

\hspace{5em}\TeXhead\verb-\foo le monde-\par\nobreak
\hspace{5em}\TeXhead{\ttfamily\fboxsep1pt \dashbox{\string\foo}le monde}\par\nobreak
\hspace{5em}\TeXhead{\ttfamily\fboxsep1pt \fbox{ Bonjour}le monde}\smallbreak

\noindent Ayant d�velopp� la commande \verb-\foo- dans sa pile, \TeX{} continue � lire le code qu'il a obtenu. Ici, cela se solderait par la lecture des caract�res �Bonjourle monde� et par leur affichage.

Il est important de comprendre que la notion de d�veloppement ne s'applique qu'� des s�quences de contr�le ou des caract�res actifs. On peut donner la d�finition suivante :

\begin{regle}[D�finition]Une \idx{s�quence de contr�le} est d�veloppable si \TeX{} peut la remplacer par un code diff�rent.\end{regle}

Les primitives n'ont pas de \idx{texte de remplacement}. Cependant, certaines d'entre elles sont d�veloppables. Nous en avons rencontr� une qui est la paire \idx\csname\linebreak[1]\verb-...-\linebreak[1]\idx\endcsname dont l'argument est le code qui se trouve entre elles. En effet, lorsque \TeX{} les ex�cute, il transforme leur argument en une \idx{s�quence de contr�le}. Cette action recoupe la d�finition donn�e juste au-dessus : le code qui est substitu� est bien diff�rent de ce qu'il y avait avant le d�veloppement.

La plupart des primitives ne sont pas d�veloppables en ce sens que si l'on force leur d�veloppement (nous verrons comment), on obtient la primitive elle-m�me. L'action de ces primitives est de provoquer une action par le processeur lorsqu'elles sont ex�cut�es par \TeX{}. Par exemple, pour la primitive \verb|\def| qui n'est pas d�veloppable, son action est de ranger dans la m�moire de \TeX{} le texte de remplacement d'une macro. Les caract�res de code de cat�gorie 11 comme �\verb-A-� ou m�me ceux dont le code de cat�gorie est moins inoffensif comme �\verb-$-� ne sont pas d�veloppables non plus. Comme les primitives non d�veloppables, ils provoquent une action via le programme \texttt{tex} qui est de placer ce caract�re dans la page pour les lettres et passer en mode math�matique\idx*{mode!math�matique} pour \verb-$-. Seuls les caract�res rendus actifs dont le code de cat�gorie est 13 peuvent se d�velopper puisque leur comportement est similaire � celui des commandes.

Prenons maintenant l'exemple suivant o� la macro \verb-\foo- admet 2 arguments :
\centrecode-\def\foo#1#2{Bonjour #1 et #2}-

\noindent Faisons l'hypoth�se que l'on stocke deux pr�noms �Alice� et �Bob� dans les deux macros suivantes :
\centrecode-\def\AA{Alice } \def\BB{Bob }-

\noindent Pour bien comprendre le m�canisme du d�veloppement, prenons � nouveau le temps d'examiner en d�tail ce qui va se passer lorsqu'on �crit :

\centrecode-\csname foo\ensdcsname\AA\BB et les autres-.

\noindent Dans ce cas, voici les �tapes par lesquelles \TeX{} va passer :
\begingroup
\fboxsep1pt
\parskip1.5pt
\def\beforecode{\ttfamily\hspace{5em}}
\begin{enumerate}[parsep=0pt,itemsep=0pt]
       \item lecture du code dont il a besoin pour former la commande \boxtoken\foo{} :\par
               {\beforecode\TeXhead\dashbox{\string\csname\ foo\string\endcsname}\string\AA\string\BB\ et les autres.}
       \item d�veloppement de ce qui a �t� lu, ce qui provoque la construction de la macro \verb-\foo- dans la pile :\par
               {\beforecode\TeXhead\fbox{\string\foo}\string\AA\string\BB\ et les autres.}
       \item la pile ne contenant pas les deux arguments requis pour la macro \verb-\foo-, ceux-ci sont donc lus � l'ext�rieur de la pile :\par
               {\beforecode\TeXhead\fbox{\rlap{\dashbox{\phantom{\string\foo\string\AA\string\BB}}}\string\foo}\string\AA\string\BB\ et les autres.}
       \item d�veloppement de \verb-\foo- et ses deux arguments qui provoque sa substitution par son texte de remplacement ;\par
               {\beforecode\TeXhead\fbox{Bonjour \string\AA\ et \string\BB} et les autres.}
       \item affichage de �Bonjour� et lecture du code jusqu'� \verb-\AA- :\par
               {\beforecode Bonjour \TeXhead\fbox{\dashbox{\string\AA} et \string\BB} et les autres.}
       \item d�veloppement de \verb-\AA- :\par
               {\beforecode Bonjour \TeXhead\fbox{Alice et \string\BB} et les autres.}
       \item affichage de �Alice et � et lecture du code jusqu'� \verb-\BB- ;\par
               {\beforecode Bonjour Alice et \TeXhead\fbox{\dashbox{\string\BB}} et les autres.}
       \item d�veloppement de \verb-\BB- :\par
               {\beforecode Bonjour Alice et \TeXhead\fbox{Bob} et les autres.}
       \item lecture du code qui ne contient plus que des caract�res inoffensifs jusqu'au �\verb-.-� :\par
               {\beforecode Bonjour Alice et Bob et les autres.\TeXhead}
\end{enumerate}
\endgroup
\grandsaut

Il arrive qu'une \idx{s�quence de contr�le} puisse �tre d�velopp�e plusieurs fois. Imaginons que l'on d�finisse deux s�quences de contr�le \verb-\A- et \verb-\B- par ce code :

\centrecode-\def\A{\B}
\def\B{Salut}-

Si l'on �crit \verb-\A- dans le code, \TeX{} va proc�der � son d�veloppement et va la remplacer par \verb-\B-. Cette \idx{s�quence de contr�le} va �tre d�velopp�e � son tour pour �tre remplac�e par � Salut � dans la pile. Dans ce cas, on dit que la macro \verb-\A- a �t� 2-d�velopp�e, c'est-�-dire qu'elle a d� subir 2 d�veloppements successifs. On pourrait se repr�senter la situation par des paquets cadeaux : la \idx{s�quence de contr�le} est le paquet cadeau (le contenant) et son d�veloppement est le contenu. Pour les deux macros \verb-\A- et \verb-\B-, il s'agit d'un syst�me de poup�es gigognes o� le paquet cadeau \verb-\A- contient le paquet \verb-\B- qui lui-m�me contient � Salut �. On comprend qu'il faut ouvrir 2 paquets pour prendre connaissance du contenu final :

\begin{centrage}
       \small\boxcs\A{\boxcs\B{Salut}}
\end{centrage}

Si au lieu de \verb-\A-, on avait �crit �\idx\csname\verb- A-\idx\endcsname�, il aurait fallu ajouter un d�veloppement de plus au d�but pour transformer ce code en \verb-\A-. Et donc c'est apr�s 3 d�veloppements que �\verb-\csname A\endcsname-� donne �Salut�.

\begin{exercice}
On d�finit trois macros de cette fa�on :

\centrecode-\def\aa{\bb}
\def\bb{\csname cc\endcsname}
\def\cc{Bonjour}-

Si on �crit dans le code \idx\csname\verb- aa-\idx\endcsname, combien de d�veloppements successifs \TeX{} doit-il effectuer pour que le code dans la pile soit �Bonjour� ?
\solution
Il suffit de compter les d�veloppements. Dans le sch�ma suivant, les fl�ches signifient �se d�veloppe en\ldots{}� :

\begin{center}
\small
\verb-\csname aa\endcsname- $\longrightarrow$ \verb-\aa- $\longrightarrow$ \verb-\bb- $\longrightarrow$ \verb|\csname cc\endcsname| $\longrightarrow$ \verb|\cc| $\longrightarrow$ Bonjour
\end{center}

Il faut donc 5 d�veloppements.
\end{exercice}

\begin{exercice}
On red�finit les macros \verb-\aa- et \verb-\bb- de cette fa�on :

\centrecode-\def\aa{\bb}
\def\bb{\def\cc{Bonjour}}-

\Qu el est le 2-d�veloppement de \verb-\aa-. Et le 3-d�veloppement ?
\solution
Le 2-d�veloppement de \verb-\aa- est �\verb-\def\cc{Bonjour}-�.

Pour le 3-d�veloppement, la question n'est pas claire. En effet, le 2-d�veloppement que l'on voit � la ligne ci-dessus n'est pas un token unique est constitu� de 11 tokens. D'ailleurs, le seul qui est susceptible de se d�velopper est \verb|\cc| puisque les autres sont soit une primitive (\verb|\def|), soit des accolades, soit des lettres. On va consid�rer que le d�veloppement ne s'applique qu'au premier token du code obtenu et la r�ponse va donc �tre : le 3-d�veloppement est identique au 2-d�veloppement, car la primitive \verb|\def| se d�veloppe en elle-m�me.
\end{exercice}

\begin{exercice}
Red�finissons les macros \verb-\aa-, \verb-\bb- et \verb|\cc| de cette fa�on :

\centrecode-\def\aa{X}
\def\bb{Y}
\def\cc{\secondoftwo\aa\bb 123}��*\secondoftwo�-

\Qu el code est obtenu sur la pile apr�s 1, 2 et 3 d�veloppements de la macro \verb-\cc- ?
\solution
�tat de la pile apr�s :
\begin{itemize}
       \item 1 d�veloppement : \verb-\secondoftwo\aa\bb 123-�*\secondoftwo
       \item 2 d�veloppements : \verb-\bb 123-
       \item 3 d�veloppements : \verb-Y123-
\end{itemize}
\end{exercice}

\noindent Les r�gles suivantes d�coulent de ce qui a �t� dit :

\begin{regle}[R�gles]
La lecture du code se fait s�quentiellement de gauche � droite et \TeX{} ne cherche pas � lire plus de tokens que ce dont il a besoin.\medbreak

Lorsque \TeX{} rencontre une s�quence de contr�le, il lit aussi ses �ventuels arguments pour proc�der � son d�veloppement qui consiste � remplacer le tout par du code. Si la pile ne contient pas assez d'arguments, \TeX{} va chercher ces arguments manquants juste apr�s la pile, c'est-�-dire dans le code source.
\end{regle}

La premi�re partie de cette r�gle concernant la lecture s�quentielle du code est extr�mement contraignante et rend certaines choses impossibles. Par exemple d�finir une \idx{s�quence de contr�le} form�e avec \idx\csname et \idx\endcsname, comme la macro \texttt\textbackslash\boxtoken{ab1c}. En effet, comme on l'a vu � la page~\pageref{construction.nom.etrange}, c'est une erreur que d'�crire :

\centrecode-\def\csname ab1c\endcsname{<code>}-

\noindent Nous avons vu �galement � la page~\pageref{non.dev.csname} que l'on ne peut �crire

\centrecode-\let\salut\csname foo\endcsname-\idx*\let

\noindent pour rendre la macro \verb|\salut| �gale � \verb|\foo|.

Concernant le d�veloppement, \TeX{} permet d'enfreindre la premi�re partie de la r�gle en offrant la possibilit�, dans une faible mesure, de d�velopper le code \emph{non lin�airement} et c'est ce que nous allons d�couvrir avec la primitive \verb|\expandafter|.

\section{La primitive \texttt{\textbackslash expandafter}}\idx*[|(]\expandafter
Il n'est pas exag�r� de dire qu'aux yeux de d�butants en \TeX, \verb|\expandafter| est une des primitives les plus myst�rieuses qui soient. Certains lui pr�tent des vertus quasi magiques et en viendraient presque � croire que diss�miner quelques \verb|\expandafter| dans un code qui ne fonctionne pas le ferait fonctionner ! Ici encore, il ne sera pas question de magie, mais au contraire de d�mystification puisque cette  primitive \verb|\expanfafter| fait une chose extr�mement simple.

Tout d'abord, elle est d�veloppable, c'est-�-dire que lorsque \TeX{} va la d�velopper, il va la remplacer par du code dans la pile. L'action de cette primitive se passe au niveau des tokens et non pas � celui des arguments. Si \verb|<x>| et \verb|<y>| sont deux tokens et si l'on �crit :

\centrecode-\expandafter<x><y>-

\noindent cela a pour effet de 1-d�velopper le token \verb-<y>- avant de lire \verb-<x>-. En fait, tout se passe comme si le \verb-\expandafter- permettait de �sauter� \verb-<x>- pour 1-d�velopper \verb-<y>- et revenir ensuite au point de d�part.

\begin{regle}
Si \verb|<x>| et \verb|<y>| sont deux \emph{tokens}, �crire

\centrecode|\expandafter<x><y>|

a pour effet, lorsque \TeX{} d�veloppe \verb|\expandafter|, de 1-d�velopper \verb|<y>| sans pour autant que la t�te de lecture ne bouge de place (et donc reste devant \verb|<x>| qu'elle n'a toujours pas lu).

Le \verb|\expandafter| disparait apr�s s'�tre d�velopp� et on obtient donc

\centrecode-<x><*y>-

o� �\verb|*|� indique le 1-d�veloppement du token \verb|<y>|.
\end{regle}

Attention, \verb|<y>| a �t� 1-d�velopp�, mais n'a pas �t� \emph{lu}. La t�te de lecture de \TeX{} n'a pas boug� dans l'op�ration. On peut se repr�senter la situation en imaginant que la t�te de lecture dispose d'une � t�te de d�veloppement �, capable sur ordre de se d�solidariser pour aller d�velopper du code non encore lu. La t�te de d�veloppement, une fois sa mission accomplie, revient sur la t�te de lecture afin que cette derni�re poursuive son travail.

Une application imm�diate est que d�sormais, nous pouvons d�finir la \idx{s�quence de contr�le} \verb|\|\boxtoken{ab1c} avec \idx\csname : il suffit de sauter le \verb|\def| avec un \verb-\expandafter- pour provoquer la formation du nom de la macro avant que \verb-\def- ne la voit :

\showcode/\expandafter\def\csname ab1c\endcsname{Bonjour}
Texte de remplacement de la macro : \csname ab1c\endcsname/

Au lieu d'�crire �\verb|\expandafter\def\csname ab1c\endcsname|�, il est pr�f�rable de d�finir une macro �\defname dont l'argument est le nom de la macro. Il est facile de faire de m�me avec �\letname.

\showcode/\def\defname#1{\expandafter\def\csname#1\endcsname}��*\defname\idx*\csname\idx*\endcsname�
\defname{ab1c}{Bonjour}��*\defname�
Texte de remplacement de \litterate|\abc1| : \csname ab1c\endcsname\par��*\litterate�
\def\letname#1{\expandafter\let\csname#1\endcsname}��*\letname�
\def\foo{abc}\letname{foo1}=\foo% rend la macro "\foo1" �gale � \foo
Texte de remplacement de \litterate|\foo1| : \csname foo1\endcsname�\idx*\char\idx*\meaning�*\litterate�/

Afin de comprendre l'utilit� du d�veloppement, tentons maintenant une exp�rience en utilisant la macro � arguments d�limit�s �\firstto@nil[|(]. Nous l'avons d�finie de la fa�on suivante � la page~\pageref{firstto@nil} :

\centrecode-\def\firstto@nil#1#2\@nil{#1}-

\noindent son texte de remplacement est donc le premier argument de ce qui se trouve entre cette macro et \verb-\@nil-.

Maintenant, si on d�finit la macro \verb-\foo- par \verb|\def\foo{Bonjour}| et que l'on �crit \verb|\firstto@nil\foo\@nil|, qu'obtient-on ?

\showcode/ \def\foo{Bonjour}\catcode`@=11
R�sultat : \firstto@nil\foo\@nil��*\firstto@nil�
\catcode`@=12/

Contrairement � ce que l'on pourrait penser, on n'obtient pas la lettre �B� mais le mot entier. C'est que, fort logiquement, \verb-\firstto@nil- a pris comme argument \verb-#1- la macro \verb-\foo- en entier tandis que l'argument d�limit� \verb|#2| est rest� vide. Il \emph{essentiel} de ne pas confondre macro et texte de remplacement : dans un cas, il y a un seul token alors que dans l'autre, il y a tous les tokens du texte de remplacement, c'est-�-dire ici les 7 lettres du mot �Bonjour�. Pour que \verb|\first@tonil| agisse sur le texte de remplacement de \verb|\foo| et non pas sur \verb|\foo| elle-m�me, il faut d�velopper \verb-\foo- \emph{avant} que \TeX{} ne lise la macro \verb-\firstto@nil-. Nous allons utiliser \verb-\expandafter- pour sauter \verb-\firstto@nil- et provoquer ce d�veloppement :

\showcode/\def\foo{Bonjour}\catcode`@=11
R�sultat : \expandafter\firstto@nil\foo\@nil
\catcode`@=12/

\noindent Le m�canisme est sch�matis� ci-dessous :

\begin{centrage}
       \small\jumptok-\firstto@nil\foo-\verb-\@nil-
\end{centrage}

\noindent La fl�che repr�sente le d�veloppement du token encadr�. Ici donc, le d�veloppement de \verb|\expandafter| va provoquer le 1-d�veloppement de \verb|\foo| et donne :

\centrecode-\firsto@nil Bonjour\@nil-

\noindent Cette exp�rience faite avec \verb|\firsto@nil| peut �tre g�n�ralis�e � n'importe quelle autre macro :

\begin{regle}
Lorsqu'on stocke des tokens dans une \verb|\<macroA>| (comme cela arrive tr�s souvent), si l'on veut mettre ces tokens dans l'argument d'une autre macro \verb|\<macroB>|, il \emph{faut} d�velopper \verb|\<macroA>| avant que \verb|\<macroB>| n'agisse.
\end{regle}

\begin{exercice}
Au lieu d'une macro, utiliser un nouveau registre de token \verb|\testtoks| pour stocker les caract�res � Bonjour �. Comment faut-il alors utiliser �\firstto@nil pour obtenir la lettre � B �?
\solution
Pour extraire le contenu du registre, il faut d�velopper la primitive \idx\the lorsqu'elle pr�c�de le registre. Ici, au lieu de 1-d�velopper la macro, il faut 1-d�velopper \idx\the\idx\toks0 :

\showcode/\newtoks\testtoks \testtoks={Bonjour}�\idx*\newtoks�
\catcode`@=11
R�sultat : \expandafter\firstto@nil\the\testtoks\@nil�\idx*\the�
\catcode`@=12/
\end{exercice}
\grandsaut

Afin de bien maitriser le d�veloppement, abandonnons la macro �\firstto@nil[|)]  pour construire une macro plus g�n�raliste \verb|\>| qui agit comme un r�v�lateur universel et qui affiche litt�ralement tout ce qui se trouve entre \verb|\>| et \verb|<| :

\centrecode|\>ensemble de tokens<|

On voudrait que \verb|\>12^&$~\foo$<| affiche �\detokenize{12^&$~\foo$}�. Pour cela, la primitive \idx\detokenize va bien nous aider. Cette primitive d�veloppable admet un argument entre accolades et le transforme en caract�res de code de cat�gorie 12 (et 10 pour l'espace). Par exemple, si on �crit \verb-\detokenize{12^&$~\foo$}-,  on obtient � \detokenize{12^&$~\foo$} �.

Il est utile de faire quelques remarques concernant \idx\detokenize : une espace est \emph{toujours} rajout�e apr�s une \idx{s�quence de contr�le}; ici, on peut la voir apr�s \verb-\foo-. Enfin, l'argument doit contenir un texte o� les accolades sont �quilibr�es. Voici le code qui permet de programmer la macro \verb|\>| �voqu�e plus haut\label{macro.>} :

\centrecode/\long\def\>#1<{\detokenize{#1}}/
\long\def\>#1<{\detokenize{#1}}

Exp�rimentons cette macro et profitons de \verb-\expandafter- pour � sauter � la macro \verb-\>- afin de d�velopper le premier token qui se trouve juste apr�s :

\showcode/\def\foo{bonjour}
a) \>\csname foo\endcsname< \par�\idx*\csname\idx*\endcsname�
b) \>\foo< \par
c) \expandafter\>\foo< \par
d) \>\foo\foo< \par
e) \expandafter\>\foo\foo</

Chaque fois qu'un \verb-\expandafter- pr�c�de \verb-\>- (cas c et e), on constate que le d�veloppement du \verb-\foo- a bien lieu tout de suite apr�s la balise. � la derni�re ligne, on voit que le premier \verb-\foo- est d�velopp� alors que le second, non concern� par le \verb-\expandafter- reste tel quel.

Maintenant, essayons de 1-d�velopper le \emph{second} \verb-\foo- de la derni�re ligne tout en laissant le premier intact. Le principe est que le d�veloppement d'un premier \verb|\expandafter| provoque le d�veloppement d'un autre situ� un token apr�s, et ainsi de suite pour finir par 1-d�velopper le token voulu. Cette capacit� que poss�dent les \verb|\expandafter| � se transmettre de proche en proche le d�veloppement conduit � appeler ce genre de structure un � pont d'\verb|\expandafter|� :

\begin{centrage}
       \small\jumptok-\>\foo\foo-\verb-<-
\end{centrage}

Une fois que les \verb-\expandafter- se sont pass� le relai pour d�velopper le second \verb-\foo-, ceux-ci disparaissent, et le code qui est pr�t � �tre lu est :

\centrecode-\>\foo Bonjour<-

\noindent ce que l'on v�rifie dans cet exemple :

\showcode/\def\foo{Bonjour} \expandafter\>\expandafter\foo\foo</

La r�gle fondamentale est la suivante :

\begin{regle}
Pour 1-d�velopper un token pr�c�d� de $n$ tokens, il faut mettre un \verb-\expandafter- devant chacun de ces $n$ tokens.
\end{regle}

Par exemple, en partant de \verb-\foo-, si l'on veut d�finir une macro \verb-\bar- dont le texte de remplacement soit �\verb-\foo Bonjour-�, alors on doit mettre un \verb-\expandafter-, repr�sent� par un � $\bullet$ � devant les 4 tokens \boxtoken{\def}, \boxtoken{\bar}, \boxtoken[]{\{} et \boxtoken{\foo} pour provoquer le 1-d�veloppement du second \verb-\foo- :

\begin{centrage}
       \small\ttfamily$\bullet$\string\def$\bullet$\string\bar$\bullet$\string{$\bullet$\string\foo\string\foo\string}
\end{centrage}

\showcode|\def\foo{Bonjour}
\expandafter\def\expandafter\bar\expandafter{\expandafter\foo\foo}
\meaning\bar|

Une application de ceci, tr�s utile en programmation, est l'ajout d'un \verb|<code>| au texte de remplacement d'une macro. Appelons �\addtomacro[|(]\label{addtomacro} la commande qui admet deux arguments dont le premier est une macro et le second est un texte qui sera ajout� � la fin du texte de remplacement de la macro. On doit pouvoir �crire :

\centrecode-\def\foo{Bonjour}
\addtomacro\foo{ le monde}-�*\addtomacro

\noindent pour qu'ensuite, la macro \verb-\foo- ait comme texte de remplacement � Bonjour le monde �. La m�thode consiste � partir de cette d�finition :

\centrecode-\long\def\addtomacro#1#2{\def#1{#1#2}}-

\noindent Si on �crit ��\addtomacro\verb-\foo{ le monde}-�, le texte de remplacement devient

\centrecode-\def\foo{\foo Bonjour}-

\noindent On le voit, le texte de remplacement va conduire � une d�finition \emph{r�cursive} de \verb-\foo- puisque le texte de remplacement de \verb|\foo| contient \verb|\foo|. Ouvrons une parenth�se et int�ressons-nous � ce qui va se passer.
\grandsaut

L'ex�cution de \verb|\foo| telle que d�finie ci-dessus va conduire � une erreur de compilation. En effet, � chaque d�veloppement, non seulement \verb|\foo| est cr��e dans la pile, mais 7 tokens (les 7 lettres du mot � Bonjour �) y sont aussi ajout�s. La pile va donc croitre tr�s rapidement, voici son contenu lors des premiers d�veloppements :
\begin{enumerate}
       \item \verb|\foo|
       \item \verb|\foo Bonjour|
       \item \verb|\foo BonjourBonjour|
       \item \verb|\foo BonjourBonjourBonjour|
       \item etc.
\end{enumerate}

Cette pile n'�tant pas infinie, le maximum va �tre rapidement atteint :

\errcode/\def\foo{\foo Bonjour}% d�finition r�cursive
\foo% l'ex�cution provoque un d�passement de la capacit� de la pile/%
{! TeX capacity exceeded, sorry [input stack size=5000].}

Augmenter cette taille ne changerait pas l'issue, m�me si des d�veloppements suppl�mentaires �taient faits.
\grandsaut

Fermons la parenth�se et revenons � \verb|\def\foo{\foo Bonjour}|. Afin d'�viter l'�cueil du d�passement de la capacit� de la pile, il faut 1-d�velopper \verb-\foo- � l'int�rieur des accolades pour qu'elle soit remplac�e par �Bonjour� et ce, \emph{avant} que \verb|\def| n'entre en action. Comme nous l'avons vu, il suffit de placer un \verb-\expandafter- devant chaque token qui pr�c�de ce \verb-\foo-. Voici le code correct qui permet de programmer la macro \verb-\addtomacro- :

\showcode|\long\def\addtomacro#1#2{%��*\addtomacro�
       \expandafter\def\expandafter#1\expandafter{#1#2}%
}
\def\foo{Bonjour}
\addtomacro\foo{ le monde}��*\addtomacro�
\meaning\foo�\idx*\meaning�|

\begin{exercice}
En utilisant �\addtomacro, �crire une macro �\eaddtomacro qui agit comme �\addtomacro sauf que le second argument est 1-d�velopp�. Ainsi, si on �crit

\centrecode-\def\foo{Bonjour} \def\world{ le monde}
\eaddtomacro\foo\world-

alors, le texte de remplacement de la macro \verb-\foo- doit �tre �Bonjour le monde�.
\solution
Si nous partons de ceci :

\centrecode-\long\def\eaddtomacro#1#2{\addtomacro#1{#2}}-

le texte de remplacement est de �\eaddtomacro est

\centrecode-\addtomacro#1{#2}-

Pour que �\addtomacro acc�de au texte de remplacement de la macro \verb|#2|, nous savons qu'� l'int�rieur des accolades, \verb-#2- doit �tre 1-d�velopp�e. Pour ce faire, il faut placer un \verb-\expandafter- devant chacun des 3 tokens qui pr�c�dent \verb-#2- :

\showcode|\long\def\eaddtomacro#1#2{%��*\eaddtomacro�
       \expandafter\addtomacro\expandafter#1\expandafter{#2}%
}
\def\foo{Bonjour} \def\world{ le monde}
\eaddtomacro\foo\world��*\eaddtomacro�
\meaning\foo�\idx*\meaning�|
\end{exercice}�*\addtomacro[|)]
\grandsaut

Nous allons maintenant construire les m�mes macros sauf qu'elles agiront sur le contenu de registres de tokens. Mais pour atteindre ce but, une r�gle va nous �tre utile\ldots{}

\begin{regle}\relax\label{primitive.suivie.par.accolade}
Les primitives qui doivent imm�diatement �tre suivies d'une accolade ouvrante ont la particularit� suivante : elles d�veloppent au maximum\idx*{d�veloppement maximal} jusqu'� trouver l'accolade ouvrante.

Nous connaissons :
\begin{itemize}
       \item \idx\lowercase et \idx\uppercase;
       \item \idx\detokenize;
       \item \idx\toks\verb*-<nombre>= - (ou \verb*-\<nom>= - si on est pass� par \idx\newtoks\verb-\<nom>-), sachant que le signe \verb|=| et l'espace qui le suit sont facultatifs.
\end{itemize}

La cons�quence est que l'on peut placer un (ou plusieurs) \verb|\expandafter| entre ces primitives et l'accolade ouvrante pour d�velopper leur argument avant qu'elles n'agissent.
\end{regle}

La m�thode va consister � tirer parti de cette r�gle. Si \verb|#1| est un registre de tokens, on va partir de

\centrecode-#1= {\the#1#2}-

\noindent et placer un \verb|\expandafter| entre \verb*|#1= | et l'accolade ouvrante pour 1-d�velopper \verb|\the#1| afin de d�livrer le contenu du registre \verb|#1| :

\showcode/\long\def\addtotoks#1#2{#1= \expandafter{\the#1#2}}��*\addtotoks\idx*\long�
\newtoks\bar�\idx*\newtoks�
\bar={Bonjour}% met "Bonjour" dans le registre
\addtotoks\bar{ le monde}% ajoute " le monde"��*\addtotoks�
\the\bar% affiche le registre�\idx*\the�/

En copiant la m�thode utilis�e avec �\eaddtomacro, il est facile de construire la macro �\eaddtotoks qui 1-d�veloppe son second argument avant de l'ajouter au contenu du registre � token \verb|#1| :

\showcode/\long\def\eaddtotoks#1#2{\expandafter\addtotoks\expandafter#1\expandafter{#2}}��*\eaddtotoks�*\addtotoks�
\bar={Bonjour}
\def\macrofoo{ le monde}
\eaddtotoks\bar\macrofoo��*\eaddtotoks�
\the\bar�\idx*\the�/

\section{D�velopper encore plus avec \texttt{\textbackslash expandafter}}
Jusqu'� pr�sent, nous nous sommes limit�s � des \verb|\expandafter| provoquant des 1-d�veloppements, mais on peut 2-d�velopper, voire plus. Pour voir comment, d�finissons les macros

\centrecode-\def\X{Bonjour} \def\Y{\X}-

\noindent et int�ressons-nous au probl�me suivant : essayons de 2-d�velopper le �\verb-\Y-� qui se trouve entre \verb-\>- et \verb-<- dans �\verb-\>\Y<-� de fa�on � obtenir l'affichage �Bonjour�.

Ce que nous savons faire, c'est 1-d�velopper \verb-\Y- :

\centrecode-\expandafter\>\Y<-

\noindent En l'�tat, ce code ne fait que 1-d�velopper \verb|\Y|. Pour 2-d�velopper, il faudrait que le \verb|\expandafter| ci-dessus agisse sur le 1-d�veloppement de \verb|\Y|. On va donc partir du code ci-dessus et faire en sorte que pr�alablement, le \verb|\Y| soit 1-d�velopp�. Nous savons comment placer les \verb-\expandafter- pour que la macro \verb-\Y- soit 1-d�velopp�e, il suffit d'en mettre un devant chaque token qui pr�c�de \verb-\Y-. Il faut donc placer un \verb-\expandafter- devant le premier \verb-\expandafter- et un autre devant \verb-\>-. On arrive au code suivant :

\centrecode-\expandafter\expandafter\expandafter\>\Y<-

\noindent Pour nous assurer que ce code va conduire au r�sultat escompt�, examinons ce qui se passe avec les conventions graphiques vues auparavant. Voici ce qui se passe dans un premier temps :

\begin{centrage}
       \small\jumptok-\expandafter\>\Y-\verb-<-
\end{centrage}

\noindent La macro \verb-\Y- est d�velopp�e en \verb-\X- et on obtient le code � \verb-\expandafter\>\X<- � dans la pile. Voici maintenant le deuxi�me temps :

\begin{centrage}
       \small\jumptok-\>\X-\verb-<-
\end{centrage}

\noindent \verb-\X- se d�veloppe bien en �Bonjour� ce qui donne :

\centrecode-\>Bonjour<-

\noindent que nous cherchions � obtenir. V�rifions-le sur cet exemple :

\showcode/\def\X{Bonjour} \def\Y{\X}
\expandafter\expandafter\expandafter\>\Y</

Ce pont d'\verb|\expandatfer| a provoqu� \emph{deux} d�veloppements pour arriver au code final et on peut parler de � pont � plusieurs niveaux �.
\grandsaut

Retenons que lorsque deux tokens \verb-<x><y>- sont dans le code, pour 2-d�velopper \verb-<y>- avant de lire \verb-<x>-, nous devons placer trois \verb-\expandafter- devant \verb-<x>- de cette fa�on :
\centrecode-\expandafter\expandafter\expandafter<x><y>-

Et si nous voulions 3-d�velopper \verb-<y>-, il faudrait ajouter des \verb|\expandafter| dans le code ci-dessus pour, au pr�alable, 1-d�velopper \verb-<y>-. Pour cela, il faudrait placer un \verb-\expandafter- devant chaque token qui pr�c�de \verb-<y>- et donc en ajouter 4 (un devant chacun des 3 \verb-\expandafter- existants et un devant \verb-<x>-). Nous aurions alors 7 \verb|\expandafter| en tout :

\centrecode-\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter<x><y>-

Pour un d�veloppement de plus de \verb-<y>- de fa�on � le 4-d�velopper, il faudrait 1-d�velopper \verb|<y>| dans le code ci-dessus et donc, ajouter 8 \verb|\expandatfer| de plus (un devant les 7 \verb-\expandafter- existants plus un devant \verb-<x>-) ce qui en ferait 15.
\grandsaut

Essayons d'en tirer une r�gle g�n�rale : soit $u_k$ le nombre d'\verb-\expandafter- plac�s devant les tokens \verb-<x><y>- qui provoquent le $k$-d�veloppement de \verb|<y>|. Si on veut proc�der � un d�veloppement de plus de \verb-<y>-, il faut ajouter $u_k+1$ \verb-\expandafter- devant \verb-<x><y>- (un devant chacun des $u_k$ \verb-\expandafter- existants et un devant \verb-<x><y>-). Pour traduire ceci par une relation de r�currence math�matique, il suffit de partir de $u_1=1$ puisque un \verb|\expandafter|
plac� devant \verb|<x><y>| provoque le 1-d�veloppement de \verb|<y>|. On a donc :

\begin{align*}
u_1&=1&u_{k+1}&=u_k+u_k+1\\
&&&=2u_k+1
\end{align*}

\noindent � l'aide d'une d�monstration math�matique facile, on en tirerait que :
\[u_k=2^k-1\]

Le raisonnement pourrait facilement �tre g�n�ralis� si plusieurs tokens pr�c�daient \verb-<y>-. La r�gle g�n�rale est la suivante et il est bon de s'en souvenir :

\begin{regle}
Pour provoquer le $k$-d�veloppement d'un token \verb|<y>| pr�c�d� par $n$ autres tokens, il faut placer $2^k-1$ \verb-\expandafter- devant chacun des $n$ tokens qui le pr�c�dent.
\end{regle}

\begin{exercice}
Reprenons les macros suivantes :

\centrecode-\def\X{Bonjour}
\def\Y{\X}-

Placer les \verb-\expandafter- dans le code ci-dessous pour que le texte de remplacement de la macro \verb-\foo- soit � Bonjour � :

\centrecode-\def\foo{\Y}-

\solution
La r�ponse se trouve dans la r�gle pr�c�dente : il faut 2-d�velopper \verb-\Y- et donc ajouter $2^2-1$, c'est-�-dire 3 \verb-\expandafter- devant chaque token qui pr�c�de \verb-\Y-. Ces tokens sont au nombre de 3 (�\verb|\def|�, �\verb|\foo|� et �\verb|{|�) et donc, il faut remplacer chaque � $\bullet$ � par 3 \verb-\expandafter- dans ce code :

\begin{centrage}
       \small$\bullet$\verb-\def-$\bullet$\verb-\foo-$\bullet$\verb-{\Y}-
\end{centrage}

\noindent Cela donne un code un peu indigeste :

\centrecode-\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\foo
\expandafter\expandafter\expandafter{\Y}-
\end{exercice}

\begin{exercice}
Placer correctement des \verb-\expandafter- dans la derni�re ligne du code ci-dessous pour que \verb-\bar- ait comme texte de remplacement � Bonjour le monde � :

\centrecode-\def\foo{Bonjour}
\def\world{ le monde}
\def\bar{\foo\world}-
\solution
Si on part de

\centrecode-\def\bar{\foo\world}-

il faut 1-d�velopper \verb|\foo| et 1-d�velopper \verb|\world| dans le texte de remplacement de \verb|\bar|.

Nous allons construire un pont d'\verb|\expandafter| en deux passes : la premi�re 1-d�veloppera une des deux macros et la deuxi�me 1-d�veloppera l'autre.

Dans un cas comme celui-ci qui est un cas particulier d'un cas plus g�n�ral, il faut commencer par placer des \verb|\expandafter| pour 1-d�velopper la macro la plus � gauche. Ceci �tant fait, la passe suivante consistera � placer des \verb|\expandatfer| pour d�velopper la macro suivante. Et ainsi de suite pour finir, lors de la derni�re passe, par le d�veloppement de la macro la plus � droite. On progresse donc de gauche � droite, c'est-�-dire dans l'ordre inverse de celui dans lequel elles seront d�velopp�es par \TeX{} lorsqu'il lira le code.

Ici donc, la premi�re passe consiste � placer des \verb|\expandafter| pour 1-d�velopper \verb|\foo|, ce qui revient � en placer un devant chaque token qui pr�c�de \verb|\foo| :

\centrecode-\expandafter\def\expandafter\foo\expandafter{\foo\world}-

Dans une deuxi�me passe, nous allons 1-d�velopper \verb-\world- et placer aussi un \verb-\expandafter- devant chaque token qui la pr�c�de, en tenant compte de ceux d�j� mis en place :

\centrecode-\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\foo
\expandafter\expandafter\expandafter
{\expandafter\foo\world}-

Bien que ne r�pondant pas aux contraintes de l'�nonc�, la macro �\eaddtomacro peut se r�v�ler utile dans un cas comme celui-ci. En effet, elle am�liore la lisibilit� du code puisqu'elle �vite ces nombreux \verb|\expandafter|. Une autre fa�on de faire aurait �t� :

\centrecode-\def\bar{}%
\eaddtomacro\bar\foo
\eaddtomacro\bar\world��*\eaddtomacro�-
\end{exercice}

La primitive \verb|\expandafter| intervenant au niveau des \emph{tokens}, il est int�ressant en programmation de disposer d'une macro, appelons-la �\expsecond[|(], qui intervient au niveau des \emph{arguments}. On voudrait qu'elle soit capable de sauter un argument entier pour 1-d�velopper le premier token de l'argument qui suit. On pourrait donc �crire :

\centrecode-\expsecond{<arg1>}{<arg2>}-

\noindent pour que le code finalement lu par \TeX{} soit

\centrecode-<arg1>{*<arg2>}-

\noindent o� l'�toile indique que le premier token de \verb|<arg2>| est 1-d�velopp�.

\begin{exercice}\label{expsecond}
Construire la macro �\expsecond en utilisant la macro auxiliaire �\swaparg[|(] qui �change 2 arguments en mettant le premier entre accolades :

\centrecode-\long\def\swaparg#1#2{#2{#1}}-

\solution
La m�thode consiste � partir de

\centrecode-\long\def\expsecond#1#2{\swaparg{#2}{#1}}-

qui, apr�s que �\swaparg ait jou� son r�le, donnerait �\verb|#1{#2}|�. Pour que le premier token de \verb|#2| soit 1-d�velopp�, il faut placer des \verb|\expandafter| dans le texte de remplacement de �\expsecond pour provoquer ce d�veloppement. Cela donne :

\centrecode-\long\def\swaparg#1#2{#2{#1}}
\long\def\expsecond#1#2{\expandafter\swaparg\expandafter{#2}{#1}}-
\end{exercice}

\begin{exercice}
Combien de d�veloppements doit subir �\expsecond\verb-{<arg1>}{<arg2>}- pour que le code qui soit effectivement � lire soit \verb-<arg1>{*<arg2>}- ?

Placer correctement des \verb|\expandafter| dans le 2\ieme{} ligne de ce code

\centrecode-\def\X{Bonjour}
\>\expsecond{\X}{\X}<-

pour qu'il affiche � \string\X{} Bonjour �. La macro \verb|\>|, programm�e � la page~\pageref{macro.>}, affiche tel quel le code qu'elle rencontre jusqu'au prochain \verb|<|.
\solution
D�veloppons �\expsecond\verb-{<arg1>}{<arg2>}- comme le fait \TeX{} :
\begin{enumerate}
       \item  \verb-\expandafter\swaparg\expandafter{<arg2>}{<arg1>}-
       \item \verb-\swaparg{*<arg2>}{<arg1>}- (les \verb|\expandafter| ont jou� leur r�le)
       \item \verb-<arg1>{*<arg2>}-
\end{enumerate}
Il faut donc 3 d�veloppements.
\medskip

Dans �\verb-\>\expsecond{\X}{\X}<-�, si l'on veut 3-d�velopper �\expsecond, il faudra mettre $2^3-1=7$ \verb-\expandafter- devant \verb-\>- :

\showcode/\long\def\swaparg#1#2{#2{#1}}��*\swaparg\idx*\long�
\long\def\expsecond#1#2{\expandafter\swaparg\expandafter{#2}{#1}}��*\expsecond\idx*\long�
\def\X{Bonjour}
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
\>\expsecond{\X}{\X}<��*\expsecond�/
\end{exercice}

\begin{exercice}
Dans quels cas �\expsecond ne fonctionne pas comme attendu ?
\solution
Si l'on examine la d�finition

\centrecode-\long\def\expsecond#1#2{\expandafter\swaparg\expandafter{#2}{#1}}-�*\expsecond

on constate que le 1-d�veloppement de l'argument \verb|#2| a lieu alors que cet argument est d�plac� et n'est plus en dernier, c'est-�-dire qu'il ne pr�c�de pas le code qui suit. D�s lors, si cet argument doit agir sur le code qui suit (avec �\gobone, �\identity, �\firstoftwo ou �\secondoftwo), il n'est plus en mesure de le faire. Dans l'exemple ci-dessous, on souhaite 1-d�velopper �\gobone pour donner � \verb|\foo| le texte de remplacement �\verb|B|� :

\errcode/\expsecond{\def\foo}\secondoftwo{A}{B}��*\expsecond�*\secondoftwo�/{Argument of \texttt{\string\secondoftwo} has an extra \char`\}}

Le 2\ieme{} argument de �\expsecond est �\secondoftwo donc, apr�s avoir 1-d�velopp� �\expsecond dans �\verb|\expsecond{\def\foo}\secondoftwo{A}{B}|�, voici ce que l'on obtient :

\centrecode-\expandafter\swaparg\expandafter{\secondoftwo}{\def\foo}-

Lorsque �\secondoftwo est 1-d�velopp�, en cherchant son premier argument, il voit �\verb|}|� et c'est l� que \TeX{} proteste car une accolade fermante ne peut pas �tre le d�but d'un argument.

Pour que �B� soit le texte de remplacement de \verb|\foo|, il aurait fallu que �\verb|\secondoftwo{A}|\linebreak[1]\verb|{B}|� soit le 2\ieme{} argument de �\expsecond :

\showcode/\expsecond{\def\foo}{\secondoftwo{A}{B}}��*\expsecond�*\secondoftwo�
\meaning\foo�\idx\meaning�/
\end{exercice}�*\expsecond[|)]�*\swaparg[|)]

La macro �\expsecond peut �tre utilis�e si son premier argument est une macro :

\centrecode-\expsecond\<macro>{<argument>}-

\noindent Dans ce cas, �\expsecond 1-d�veloppe l'argument de la macro avant d'ex�cuter la macro. C'est pourquoi la macro �\expsecond a un alias ��\exparg� d�fini par \idx\let dont le nom sugg�re davantage que l'argument d'une macro a �t� d�velopp�.

\begin{exercice}
En reprenant le m�me principe que �\exparg, d�finir une macro �*\exptwoargs

\centrecode-\exptwoargs\<macro>{argument 1}{argument 2}-

\noindent qui 1-d�veloppe les 2 premiers tokens des deux arguments avant de lancer la \verb|\<macro>|
\solution
Deux appels imbriqu�s � �\exparg conduisent au r�sultat :

\centrecode-\def\exptwoargs#1#2#3{\expsecond{\expsecond{#1}{#2}}{#3}}-

\noindent Comme l'argument \verb|#3| se trouve une seule fois dans le texte de remplacement de la macro et � la fin de celui-ci, il est possible de ne pas le faire lire par �\exptwoargs :

\showcode/\def\exptwoargs#1#2{\expsecond{\expsecond{#1}{#2}}}��*\exptwoargs�*\expsecond�
\def\foo{Bonjour}\def\bar{ le monde}
\def\displaytwoargs#1#2{\detokenize{#1#2}}% affiche tels quels les arguments
\exptwoargs\displaytwoargs\foo\bar��*\exptwoargs�/
\end{exercice}

Une macro plus g�n�rale, capable de d�velopper plusieurs arguments sera programm�e plus loin (voir page~\pageref{eargs}).

\section{La primitive \texttt{\textbackslash edef}}\idx*[|(]\edef
On a vu que  \verb-\expandafter- permettait de contr�ler finement la profondeur de d�veloppement moyennant, c'est vrai, de longs et laborieux ponts d'\idx[|)]\expandafter. Mais il existe des endroits o� \TeX{} d�veloppe au maximum\idx*[|(]{d�veloppement maximal} ce qu'il rencontre. Attention, il s'agit bien d'un d�veloppement et non pas d'une ex�cution. Le plus c�l�bre de ces endroits est le texte de remplacement des macros d�finies avec la primitive \verb|\edef|. Cette primitive fonctionne comme sa s\oe ur \verb-\def- sauf que tout ce qui se trouve � entre les accolades est d�velopp� au maximum et ce qui en r�sulte est le \idx{texte de remplacement} de la macro d�finie par \verb|\edef|. Essayons :

\showcode/\def\aa{Bonjour}\def\bb{\aa}
\def\cc{ le monde}
\edef\foo{\bb\cc}
\meaning\foo�\idx*\meaning�/

On constate que le texte de remplacement de \verb-\foo- contient le 2-d�veloppement de \verb|\bb| et le 1-d�veloppement de \verb|\cc|. Ces d�veloppements sont les plus profonds que l'on puisse faire puisqu'ensuite on ne trouve plus que des lettres ou des espaces. Le texte de remplacement de \verb-\truc- est bien � Bonjour le monde �.

Comme pour \verb-\def-, on peut aussi sp�cifier qu'une macro d�finie avec \verb|\edef| admet des arguments, et on utilise pour cela la m�me syntaxe \verb|#<chiffre>|, aussi bien pour le \idx{texte de param�tre} que pour le texte de remplacement. Le d�veloppement maximal fait lors de la d�finition concerne tout ce qui se trouve dans le \idx{texte de remplacement} \emph{� l'exception} des emplacements des arguments qui ont la syntaxe \verb|#<chiffre>|. Les arguments, qui seront lus plus tard lorsque la macro sera appel�e, seront ins�r�s tels quels � la place de \verb|#<chiffre>| : ils ne sont donc pas soumis au d�veloppement maximal.

On peut le constater ici o� la macro \verb-\ee- est d�finie avec un \verb-\edef- et admet un argument. � l'aide d'\verb-\expandafter-, on provoque le 1-d�veloppement de la macro \verb-\ee- dont l'argument est la macro \verb-\dd-. On peut constater que cet argument �\verb-\dd-� reste non d�velopp� bien qu'il soit l'argument d'une macro d�finie avec \verb-\edef- :

\showcode/\def\aa{Bonjour } \def\bb{\aa} \def\cc{le } \def\dd{ monde}
\edef\ee#1{\bb\cc#1 !!!}
\meaning\ee\par�\idx*\meaning�
\expandafter\>\ee{\dd}</

\begin{regle}
La primitive \verb-\edef- a la m�me syntaxe et les m�mes actions que \verb-\def-, c'est-�-dire qu'elle stocke un \idx[|etc]{texte de remplacement}\forbidindex{texte de remplacement} associ� � une \idx{s�quence de contr�le}. La diff�rence r�side dans le fait que la totalit� du texte de remplacement est d�velopp�e \emph{au maximum} avant que l'assignation soit faite.

Le d�veloppement s'applique au texte de remplacement \emph{hors arguments} symbolis�s par \verb|#<chiffre>|. Ceux-ci, qu'ils soient d�limit�s ou pas, seront ins�r�s tels qu'ils seront lus dans le texte de remplacement (qui lui aura �t� pr�alablement d�velopp�).

La primitive \idx\xdef effectue les m�mes actions que \verb|\edef| sauf que la d�finition faite est globale.
\end{regle}

\subsection{\texttt{\char`\\noexpand} pour contrer \texttt{\char`\\edef}}\idx*[|(]\noexpand
Cette primitive \verb-\edef- se r�v�le fort utile, et rend de grands services. Mais dans son argument o� tout est d�velopp� au maximum, on voudrait pouvoir bloquer le d�veloppement d'une \idx{s�quence de contr�le}. Par exemple, si l'on �crit

\centrecode-\edef\foo{\aa\bb\cc}-

\noindent comment laisser \verb-\aa- et \verb-\cc- se d�velopper au maximum tout en bloquant le d�veloppement de \verb-\bb- ? C'est l� qu'une nouvelle primitive entre en jeu, il s'agit de \verb-\noexpand-.

\begin{regle}
La primitive d�veloppable \verb|\noexpand| bloque le d�veloppement du token $x$ qui la suit. Elle a pour effet, lorsqu'elle se 1-d�veloppe, d'�tre le token $x$ lui-m�me. Si $x$ est une s�quence de contr�le qui aurait �t� d�velopp�e, $x$ est rendu temporairement �gal � \verb|\relax|.
\end{regle}

\showcode|\def\foo{123xyz}
a) signification du 1-d�veloppement d'un \litterate-\noexpand- :�\idx*\string\idx*\noexpand�*\litterate�
  \expandafter\meaning\noexpand\foo�\idx*\meaning�

b) ex�cution d'un \litterate-\noexpand- : \noexpand\foo% identique � \relax

c) 1-d�veloppement de \litterate-\noexpand- dans le texte de remplacement de
  \litterate-\bar- :��*\litterate�
  \expandafter\def\expandafter\bar\expandafter{\noexpand\foo}
  \meaning\bar�\idx*\meaning�|

Le dernier cas montre qu'entre le moment du 1-d�veloppement de \verb|\noexpand|\linebreak[1]\verb|\foo| et le moment o� \TeX{} lit ce 1-d�veloppement, plusieurs choses sont faites (lecture et ex�cution du \verb|\def| suivie de la lecture \verb|\bar| et de l'accolade ouvrante). Entre temps, le d�veloppement initi� par le pont d'\verb|\expandafter| s'est arr�t�, signant la mort du \verb|\relax| temporaire qui est donc redevenu \verb|\foo|.
\grandsaut

Dans le code � \verb-\edef\foo{\aa\bb\cc}-�, tentons maintenant de bloquer le d�veloppement de \verb|\bb| :

\showcode/\def\aa{Bonjour}\def\bb{\aa}\def\cc{\bb}
a) \edef\foo{\aa\noexpand\bb\cc}\meaning\foo  \qquad b) ex�cution : \foo\par�\idx*\meaning�
c) \edef\foo{\aa\noexpand{\aa\cc}}\meaning\foo\qquad d) ex�cution : \foo/

Tout se passe comme pr�vu au a) pour la premi�re d�finition de \verb-\foo- avec \verb-\edef- : le \verb-\noexpand- qui pr�c�de \verb-\bb- emp�che bien son d�veloppement.

� la deuxi�me ligne (cas c), on a tent� bien maladroitement de bloquer le d�veloppement de ce qui se trouve entre accolades. Ceci �choue puisque \verb-\noexpand- bloque le d�veloppement du \emph{token} qui suit et qui est dans ce cas �\cidx\{�. Cette accolade ouvrante n'a d'ailleurs nul besoin d'�tre prot�g�e d'un d�veloppement puisqu'elle n'est pas d�veloppable (et elle se d�veloppe donc en elle-m�me). Pour bloquer le d�veloppement de plusieurs s�quences de contr�le, il \emph{faut} mettre un \verb-\noexpand- devant chacune d'elles !

\subsection{\texttt{\char`\\unexpanded} pour contrer \texttt{\char`\\edef}}
Multiplier les \verb-\noexpand- et en �crire autant qu'il y a de tokens � prot�ger peut �tre lourd, voire impossible si on ne connait pas le nombre de tokens lorsqu'on manipule l'argument d'une macro par exemple. Pour contourner cette difficult�, on peut utiliser la primitive \idx\unexpanded de \eTeX{} dont le d�veloppement est de bloquer le d�veloppement du texte entre accolades qui suit la primitive.

Voici deux fa�ons de faire �quivalentes, la premi�re en pla�ant un \verb|\noexpand| devant \verb|\bb| et \verb|\aa| la seconde en mettant ces deux tokens dans l'argument de la primitive \verb|\unexpanded| :

\showcode/\def\aa{Bonjour}\def\bb{Au revoir}
a) \edef\truc{\aa\noexpand\bb\noexpand\aa\bb}\meaning\truc \par�\idx*\meaning�
b) \edef\truc{\aa\unexpanded{\bb\aa}\bb}\meaning\truc�\idx*\meaning�/\idx*[|)]\noexpand

La primitive \idx\unexpanded, tout comme \idx\detokenize et d'autres, fait partie des primitives qui doivent �tre suivies d'une accolade ouvrante. Ces primitives initient un d�veloppement maximal jusqu'� ce qu'elles rencontrent une accolade ouvrante (voir r�gle page~\pageref{primitive.suivie.par.accolade}). On peut donc intercaler un ou plusieurs \idx\expandafter entre ces primitives et l'accolade ouvrante de fa�on � proc�der au d�veloppement du (ou des) premiers tokens du texte entre accolades.

\subsection{\texttt{\char`\\the\char`\\toks\codeelement{nombre}} pour contrer  \texttt{\char`\\edef}}\idx*\toks
Il existe un autre moyen qui ne fait pas appel � \eTeX{} et qui permet de bloquer le d�veloppement dans un \verb|\edef|. Il s'agit du contenu d'un registre de tokens : dans le texte de remplacement d'un \verb|\edef|, le contenu d'un registre de tokens obtenu par le d�veloppement de \idx\the\linebreak[1]\idx\toks\linebreak[1]\verb|<nombre>| (ou par �\verb|\the|\linebreak[1]\verb|<nom d'un registre>|�) n'est pas d�velopp�.

Voici l'exemple pr�c�dent trait� avec un registre � token (ici, nous prenons le registre \no0) :

\showcode|\def\aa{Bonjour}\def\bb{Au revoir}
\toks0={\aa\bb}�\idx*\toks�
\edef\foo{\aa\the\toks0 \bb}�\idx*\toks�
\meaning\foo�\idx*\meaning�|

\subsection{Prot�ger une macro avec \texttt{\char`\\protected}}
Tout comme on peut d�clarer une macro �\idx\long� ou �\idx\global� lors de sa d�finition, on peut aussi d�clarer qu'on souhaite d�finir une macro � prot�g�e �. On entend � prot�g�e contre le d�veloppement maximal dans l'argument d'une primitive �. Pour ce faire, il faut utiliser la primitive de \eTeX {} �\idx\protected� et la placer avant le \verb|\def| (ou \verb|\edef|) qui effectue la d�finition. La macro ainsi d�finie ne se d�veloppera pas dans un \verb|\edef| :

\showcode/\def\aa{Bonjour}
\protected\def\bb{ le}% \ bb est prot�g�e !�\idx*\protected�
\def\cc{ monde}

\edef\foo{\aa\bb\cc}
Signification de \string\foo~: \meaning\foo \par�\idx*\meaning�
Ex�cution de \string\foo~: \foo�\idx*\string�/

Il faut bien comprendre que la macro est prot�g�e \verb|\bb|d'un d�veloppement est maximal, mais pas de l'action de \verb|\expandafter|. Voici comment on peut 1-d�velopper \verb|\bb| dans le texte de remplacement de \verb|\edef| avec un \verb|\expandafter| :

\showcode/\def\aa{Bonjour}
\protected\def\bb{ le}�\idx*\protected�
\def\cc{ monde}

\edef\foo{\expandafter\aa\bb\cc}% le \expandafter 1-d�veloppe \bb
\meaning\foo/

\subsection{Les moyens de bloquer le d�veloppement maximal}\label{bloquer.developpement.maximum}
Il faut savoir est que certaines primitives (\idx\edef, \idx\xdef, \idx\csname\linebreak[1]\verb|...|\linebreak[1]\idx\endcsname que nous connaissons mais aussi \idx\message, \idx\write et \idx\errmessage que nous verrons plus tard) d�veloppent au maximum ce qui est dans leur argument\footnote{Il y a aussi \texttt{\char`\\special}, \texttt{\char`\\mark} et \texttt{\char`\\marks} qui ne seront pas �tudi�es dans ce livre. Pour �tre complet, il faut signaler que  le d�veloppement maximal est aussi en marche dans un alignement lorsque \TeX{} recherche un \texttt{\char`\\omit} ou un \texttt{\char`\\noalign}.}. Les m�thodes pour contrer ce d�veloppement maximal valent aussi bien pour \verb|\edef| que pour n'importe quelle autre de ces primitives. Voici le r�sum� des m�thodes que nous avons vues :

\begin{regle}
Il existe 4 moyens de bloquer le d�veloppement maximal dans les arguments de certaines primitives :
\begin{enumerate}
       \item mettre un \idx\noexpand devant chaque token dont on veut bloquer le d�veloppement;
       \item placer les tokens dont on veut bloquer le d�veloppement dans l'argument de la primitive \idx\unexpanded de \eTeX{};
       \item stocker au pr�alable tous les tokens dont on veut bloquer le d�veloppement dans un \verb|<registre de token>|\idx*{registre!token} et �crire dans l'argument de la primitive \idx\the\verb|<registre de token>|;
       \item lorsqu'on d�finit une macro, il est possible de faire pr�c�der le \verb|\def| de la primitive \idx\protected de \eTeX{} pour emp�cher le d�veloppement maximal de cette macro.
\end{enumerate}
\end{regle}\idx*[|)]\edef{}\idx*[|)]{d�veloppement maximal}

\section{Code purement d�veloppable}\idx*[|(]{code purement d�veloppable}
On pourrait penser que la primitive \verb|\edef| peut simuler une � ex�cution � pour mettre dans la \idx{s�quence de contr�le} qu'elle d�finit le � r�sultat � de l'ex�cution du \idx{texte de remplacement}\footnote{On peut stocker l'affichage r�sultant d'un code arbitraire � l'aide des registres de boites que nous verrons plus tard.}. Il s'agit g�n�ralement d'une erreur, et pour comprendre pourquoi, il faut parler de ce qu'est du � code purement d�veloppable �.

Afin de mieux comprendre de quoi il s'agit, prenons un exemple simple, n'ayant aucun int�r�t si ce n'est p�dagogique. Supposons que la macro \verb|\foo| a comme texte de remplacement �abc�, ce qui suppose qu'un \verb|\def\foo{abc}| a �t� rencontr� auparavant. Voici un code �l�mentaire qui d�finit une macro \verb|\foo| et qui l'ex�cute :

\showcode/\def\foo{Bonjour}% d�finition
\foo% ex�cution/

Ce code de deux lignes n'est pas purement d�veloppable. Essayons de comprendre pourquoi en le mettant dans un \verb|\edef| pour d�finir la macro \verb|\bar| :

\centrecode-\edef\bar{\def\foo{Bonjour}\foo}-

Voici ce que va faire \TeX{} lorsqu'il va d�velopper au maximum le code dans le texte de remplacement de \verb|\edef| :

\begin{enumerate}
       \item la primitive non d�veloppable \verb|\def| se d�veloppe en elle-m�me et reste donc inchang�e ;
       \item les deux occurrences de \verb|\foo| vont �tre d�velopp�es et donc remplac�es par � abc �.
\end{enumerate}

Le texte de remplacement de \verb|\bar| sera donc :

\centrecode-\def abc{Bonjour}abc-

V�rifions-le :

\showcode/\def\foo{abc}
\edef\bar{\def\foo{Bonjour}\foo}
\meaning\bar�\idx*\meaning�/

Ce texte de remplacement comporte une erreur, car apr�s un \verb|\def|, on \emph{doit} trouver une \idx{s�quence de contr�le} (et non pas des caract�res normaux comme a, b et c). Mais cette erreur n'apparait pas lors de la d�finition de\verb|\bar| car \TeX{} effectue les assignations sans proc�der � l'analyse du texte de remplacement. Ce n'est que si l'on cherche � ex�cuter la macro \verb|\bar|, et donc � ex�cuter son texte de remplacement que \TeX {} �mettra le message d'erreur � \texttt{Missing control sequence} �.

\begin{exercice}
D�crire ce qui se passerait si l'on �crivait le code ci-dessous alors que la macro \verb|\foo| n'est pas d�finie.

\centrecode-\edef\bar{\def\foo{Bonjour}\foo}-

\solution

Lors du d�veloppement maximal de \verb|\foo|, celle-ci n'�tant pas d�finie, \TeX{} �mettrait le message d'erreur �\texttt{Undefined
control sequence}�.
\end{exercice}

La conclusion est donc sans appel : que \verb|\foo| soit d�finie ou pas, le code n'est pas purement d�veloppable. On pourrait r�torquer que pour ce code soit purement d�veloppable, il suffirait de bloquer le d�veloppement de \verb|\foo| en se servant de la primitive \idx\noexpand :

\showcode/\def\foo{abc}
\edef\bar{\def\noexpand\foo{Bonjour}\noexpand\foo}�\idx*\noexpand�
Signification : \meaning\bar\par�\idx*\meaning�
Ex�cution : \bar/

Peut-on dire que le code, enrichi de \idx\noexpand, est purement d�veloppable ? En fait, tout d�pend de ce que l'on attendait ! Si l'on voulait simplement construire un code ex�cutable stock� dans une macro, alors oui. Mais dans la grande majorit� des cas, on attend qu'un code purement d�veloppable se r�duise, lors de son d�veloppement maximal, aux caract�res affich�s si ce code �tait ex�cut�.

\begin{regle}
Un code est purement d�veloppable si son d�veloppement maximal se r�duit aux caract�res qui auraient �t� affich�s s'il avait �t� ex�cut� par \TeX.

Dans la majorit� des cas, un tel code ne doit �tre constitu� que caract�res (ceux que l'on souhaite dans l'affichage final) ainsi que de s�quences de contr�le ou caract�res actifs \emph{d�veloppables}. Citons :
\begin{itemize}
       \item du c�t� des primitives : \idx\expandafter, \idx\number, \idx\the, \idx\string ainsi que les primitives de \eTeX{} \idx\detokenize et \idx\unexpanded. Tous les tests de \TeX{} que nous verrons plus tard sont d�veloppables. Il y a aussi deux primitives de \eTeX{}, \idx\numexpr et \idx\dimexpr qui seront �tudi�es dans la partie suivante;
       \item les macros d�finies par l'utilisateur, qu'elles soient � arguments d�limit�s ou pas, pourvu que leur d�veloppement maximal soit constitu� des caract�res que l'on souhaite dans l'affichage final.
\end{itemize}
\end{regle}\idx*[|)]{code purement d�veloppable}

\section{Propager le d�veloppement}
\subsection{Lier des zones de d�veloppement maximal}
Dans certaines zones bien sp�cifiques, le d�veloppement est maximal\idx*{d�veloppement maximal} et donc, dans ces zones, le code doit �tre purement d�veloppable.

L'expression � propager le d�veloppement � signifie mettre en \oe uvre des m�thodes pour que ces zones de d�veloppement maximal se transmettent de proche en proche le d�veloppement. Le but est de d�velopper des territoires tr�s �loign�s de l'endroit o� le premier d�veloppement a eu lieu.

Parfois, du code \TeX{} est constitu� de zones de d�veloppement maximal entrecoup�es de zones � normales � o� ce d�veloppement maximal n'existe pas. Le sch�ma ci-dessous repr�sente une de ces situations o� les zones de d�veloppement maximal sont encadr�es et les tokens des zones normales sont repr�sent�s par �$\ast$�. La t�te de lecture de \TeX{} est repr�sent�e par \TeXhead{} :

\begin{centrage}
\small\fboxsep0pt
\TeXhead$\ast$\fbox{\strut\kern1.5cm }$\ast$\fbox{\strut\kern1.5cm }$\ast\ast$\fbox{\strut\kern1.5cm }$\ast x$
\end{centrage}

Il est possible, sans d�placer la t�te de lecture, de 1-d�velopper le token $x$. Pour cela, on va amorcer le d�veloppement de la premi�re zone de d�veloppement maximal en mettant un \idx\expandafter juste avant le premier token �$\ast$�. Par la suite, il faudra exporter le d�veloppement hors des zones encadr�es � l'aide d'un \verb|\expandafter| plac� en derni�re position. Un pont d'\verb|\expandafter| prend ensuite le relai dans la zone normale pour communiquer le d�veloppement � la zone encadr�e suivante. � la fin de la derni�re zone, un pont d'\verb|\expandafter| permettra d'atteindre le token $x$ pour le 1-d�velopper. En notant �$\bullet$� la primitive \verb|\expandafter|, voici ce que devient le sch�ma :

\begin{centrage}
\small\fboxsep0pt
\TeXhead$\bullet\ast$\fbox{\strut\kern1.5cm $\bullet$}$\bullet\ast$\fbox{\strut\kern1.5cm $\bullet$}$\bullet\ast${}$\bullet\ast$\fbox{\strut\kern1.5cm $\bullet$}$\bullet\ast${}$x$
\end{centrage}

\begin{exercice}
\Qu e faudrait-il modifier dans ce sch�ma pour provoquer le 2-d�veloppement du token $x$ ?

\solution
Tout restant �gal par ailleurs, il faut initier un pont d'\verb|\expandafter| � deux passes � la fin de la derni�re zone de d�veloppement maximal, c'est-�-dire mettre 3 \idx\expandafter au lieu d'un seul :

\begin{centrage}
\small\fboxsep0pt
\TeXhead$\bullet\ast$\fbox{\strut\kern1.5cm $\bullet$}$\bullet\ast$\fbox{\strut\kern1.5cm $\bullet$}$\bullet\ast${}$\bullet\ast$\fbox{\strut\kern1.5cm $\bullet${}$\bullet${}$\bullet$}$\bullet${}$\bullet${}$\bullet\ast${}$x$
\end{centrage}
\end{exercice}

\subsection{�tude d'un cas}
Pour illustrer ce propos, passons � un cas plus concret, quoiqu'encore tr�s th�orique. Supposons qu'avant de lire les macros \verb-\foo- et \verb-\bar-, nous devions provoquer le 2-d�veloppement de la macro \verb-\wee- et le 1-d�veloppement de \verb-\fin- dans le code suivant :

\centrecode-\foo\bar\wee\fin-

\noindent Le nombre d'\idx\expandafter n�cessaires est assez important. Essayons de les compter ! Pla�ons mentalement les \verb|\expandafter| pour provoquer tour � tour le d�veloppement des macros prises \emph{de gauche � droite}, c'est-�-dire que nous allons d'abord chercher � d�velopper \verb|\wee| qui est la plus � gauche des deux macros. Ensuite, nous partirons du code obtenu et chercherons � d�velopper \verb|\fin|.

Pour 2-d�velopper \verb|\wee|, il faut placer $2^2-1=3$ \idx\expandafter devant chaque token qui la pr�c�de ce qui fait $3\times2=6$ \idx\expandafter, not�s $\bullet$:

\begin{centrage}
\small$\bullet\bullet\bullet$\litterate-\foo-$\bullet\bullet\bullet$\litterate-\bar\wee\fin-
\end{centrage}

\noindent Dans ce code, le nombre de tokens qui pr�c�dent \verb-\fin- devient �gal � 9 : nous avons les 6 \idx\expandafter que nous venons de placer et les 3 s�quences de contr�le \verb|\foo|, \verb|\bar| et \verb|\wee|. Pour 1-d�velopper \verb|\fin|, il faut mettre un \verb|\expandafter| devant chaque token qui pr�c�de \verb|\fin| ce qui fait 9 \verb|\expandatfer| de plus et porte donc leur nombre total � $6+9=15$. Voici le code obtenu :

\begin{centrage}
\small$\bullet\bullet\bullet\bullet\bullet\bullet\bullet$\litterate-\foo-$\bullet\bullet\bullet\bullet\bullet\bullet\bullet$\litterate-\bar-$\bullet$\litterate-\wee\fin-
\end{centrage}

Venons-en maintenant aux zones de d�veloppement maximal et au lieu d'�crire directement le nom des 4 macros, aidons-nous de la paire \verb-\csname- et \verb-\endcsname- :

\centrecode-\csname foo\expandafter\endcsname
\csname bar\expandafter\endcsname
\csname baz\expandafter\endcsname
\csname fin\endcsname-

Le r�le des \idx\expandafter mis � chaque fin de zone de d�veloppement maximal (sauf la derni�re) est de transmettre le d�veloppement en dehors de la zone de d�veloppement maximal pour toucher le \idx\csname suivant qui commande � son tour le d�veloppement maximal jusqu'au prochain \idx\endcsname. L'\verb|\expandafter| se trouvant en fin de zone transmet � son tour le d�veloppement au \verb|\csname| suivant, et ainsi de suite jusqu'au dernier \verb-\endcsname- qui n'est pas pr�c�d� d'un \idx\expandafter et stoppe donc cet enchainement. La structure est clairement celle que l'on voyait dans le sch�ma de la section pr�c�dente : externaliser le d�veloppement pour d�clencher le d�veloppement d'une nouvelle zone de d�veloppement maximal pour, en r�it�rant la man\oe uvre, transmettre tr�s loin la flamme du d�veloppement. Voici le sch�ma qui traduirait cette situation (ici, aucun token ne se trouve entre les zones de d�veloppement maximal) :

\begin{centrage}
\small\fboxsep0pt
\TeXhead\fbox{\strut\kern1.5cm $\bullet$}\thinspace\fbox{\strut\kern1.5cm $\bullet$}\thinspace\fbox{\strut\kern1.5cm $\bullet$}\thinspace\fbox{\strut\kern1.5cm }
\end{centrage}

Le code donn� ci-dessus se 1-d�veloppe en � \verb-\foo\bar\wee\fin- �. En voici la preuve :

\showcode/\long\def\>#1<{\detokenize{#1}}�\idx*\long\idx*\detokenize�
\expandafter\>% provoque le 1-d�veloppement de :
\csname foo\expandafter\endcsname�\idx*\csname\idx*\endcsname�
\csname bar\expandafter\endcsname
\csname wee\expandafter\endcsname
\csname fin\endcsname</

Dans le code ci-dessus, aucune \idx{s�quence de contr�le} n'est d�velopp�e. Pour provoquer le 1-d�veloppement de \verb-\fin-, il suffit de mettre 3 \idx\expandafter apr�s �wee� au lieu d'un seul. En suivant le m�me raisonnement, pour 2-d�velopper \verb-\wee-, il faut 3-d�velopper \verb-\csname-\linebreak[1] \verb-baz-\linebreak[1]\verb-\endcsname- et donc placer 7 \idx\expandafter apr�s �bar�. Cela donne le code :

\centrecode-\csname foo\expandafter\endcsname
\csname bar\expandafter\expandafter\expandafter\expandafter
  \expandafter\expandafter\expandafter\endcsname
\csname wee\expandafter\expandafter\expandafter\endcsname
\csname fin\endcsname-

\noindent Pour nous assurer que ce code fonctionne correctement, d�finissons \verb-\wee- pour que son 2-d�veloppement soit �XX� et \verb-\fin- pour que son 1-d�veloppement soit �YY� :

\showcode/\long\def\>#1<{\detokenize{#1}}�\idx*\long\idx*\detokenize�
\def\fin{YY} \def\wee{\weeA} \def\weeA{XX}
\expandafter\>%
\csname foo\expandafter\endcsname�\idx*\csname\idx*\endcsname�
\csname bar\expandafter\expandafter\expandafter\expandafter
          \expandafter\expandafter\expandafter\endcsname
\csname wee\expandafter\expandafter\expandafter\endcsname
\csname fin\endcsname</

Le premier \idx\expandafter qui pr�c�de \verb-\>- suffit � atteindre, de zone de d�veloppement en zone de d�veloppement, la toute fin de ce code avant m�me que le premier nom de \idx{s�quence de contr�le} \verb-\foo- ne soit form�.

\begin{exercice}
O� faut-il placer des \idx\expandafter dans � \verb-\>\foo\bar\wee\fin<- � pour obtenir la m�me chose que dans l'exemple pr�c�dent ?
\solution
Il faut les 15 \idx\expandafter d�j� vus sauf qu'il faut sauter le token \verb|\>| au d�part. On a d�j� calcul� qu'il faut 7 \idx\expandafter avant \verb-\foo-, il en faut �galement 7 pour sauter \verb-\>- qui vient en premi�re position. Cela nous fait $15+7=22$ \idx\expandafter (au lieu de 12 avec \idx\csname et \idx\endcsname) :

\showcode/\long\def\>#1<{\detokenize{#1}}�\idx*\long\idx*\detokenize�
\def\fin{YYY} \def\wee{\weeA} \def\weeA{XXX}
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
\>%
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
\foo
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
\bar
\expandafter\wee\fin</
\end{exercice}

\subsection{\Qu 'est-ce qu'un nombre ?}
La notion de nombre (compris comme nombre \emph{entier}) �tant �troitement li�e � celle de d�veloppement, il est temps d'aborder ce sujet.\grandsaut

Tout d'abord, il est faux de croire que lorsque \TeX{} ex�cute le code

\centrecode-le nombre 123 est impair-

\noindent il \emph{lit} le nombre 123. Il ne fait qu'afficher s�quentiellement les caract�res �1� puis �2� et �3� sans pour autant que ces caract�res ne soient isol�s et analys�s comme un tout formant un nombre entier. Pour que \TeX{} d�clenche la lecture d'un nombre, il faut qu'il se trouve � un endroit o� il s'attend � en lire un.

Nous avons d�j� rencontr� plusieurs cas o� \TeX{} doit lire un nombre. C'est le cas pour les primitives \verb|\catcode|, \idx\lccode et \idx\uccode dont la syntaxe compl�te est

\begin{centrage}
       \small$\left.\vcenter{\hbox{\verb|\catcode|}\par\hbox{\verb|\lccode|}\par\hbox{\verb|\uccode|}}\right\}$\verb-<nombre>= <nombre>-
\end{centrage}

\noindent o� le signe \verb|=| et l'espace qui le suit sont facultatifs.

Nous avons vu qu'apr�s la primitive \idx\toks, \TeX{} attend le \verb|<nombre>| correspondant au registre de tokens auquel on veut acc�der. Nous savons �galement qu'apr�s la primitive \verb|\number|, \TeX{} s'attend � lire un nombre pour le convertir en chiffres arabes et en base 10. Un \verb|<nombre>| est �galement attendu apr�s la primitive \idx\char et le tout se traduit par l'affichage du caract�re dont le code de caract�re est \verb|<nombre>|.

Pour �tre complet concernant les caract�res affich�s via \idx\char, il est possible d'utiliser la primitive \idx\chardef dont la syntaxe est

\centrecode-\chardef\<macro>= <nombre>-

\noindent Comme pour \verb|\catcode|, \idx\lccode et \idx\uccode, le signe �=� et l'espace qui le suit sont facultatifs. L'action qu'effectue ce code est de rendre la \verb|\<macro>| �quivalente � \verb|\char<nombre>|. L'�quivalence dont il est question ici ressemble � celle effectu�e avec \verb|\let|. Ainsi, si on �crit :

\centrecode-\chardef\foo= 65-

\noindent alors, la macro \verb|\foo| sera �quivalente � \idx\char\verb|65| et produira un �A� � l'affichage.

Une \verb|\<macro>| d�finie avec \idx\chardef rev�t une dualit� int�ressante : lorsque \TeX{} s'attend � lire un nombre, cette \verb|\<macro>| est alors comprise comme un nombre. Avec la macro \verb|\foo| ci-dessus, le nombre lu serait 65.

\showcode/\chardef\foo65 �\idx*\chardef�
a) |\foo|\qquad % employ�e seule, \foo affiche un A�\idx*\qquad�
b) |\number\foo|\qquad % si TeX lit un nombre, \foo est le nombre 65�\idx*\number�/

Comme il n'y a que 256 caract�res possibles\footnote{Pour les moteurs 8 bits, car les moteurs \utf en ont beaucoup plus.}, les primitives \idx\char et \idx\chardef ne peuvent prendre en compte que des nombres compris entre 0 et 255. Le mode math�matique\idx*{mode!math�matique} requiert d'afficher beaucoup plus de caract�res que ces 256, aussi il existe les primitives \idx\mathchar et \idx\mathchardef qui sont au mode math�matique\idx*{mode!math�matique} ce que sont \idx\char et \idx\chardef au mode texte. Le caract�re dual d'une macro d�finie par \idx\mathchardef existe sauf que le nombre qu'elle peut repr�senter est compris entre 0 et \numprint{32767}\footnote{Voir le \TeX book, page 181.} et lorsqu'elle est utilis�e pour afficher un caract�re, le mode math�matique doit �tre en vigueur.

\showcode/\mathchardef\foo4944 �\idx*\mathchardef�
a) |$\foo$|\qquad % en mode math, affiche le signe "somme" (uniquement en mode maths)�\idx*\qquad�
b) |\number\foo|\qquad % si TeX lit un nombre, \foo est 4944�\idx*\number�/

Il est temps de donner la d�finition d'un nombre et montrer en quoi elle est li�e au d�veloppement.

\label{definition.entier}\begin{regle}
\relax\idx*{nombre!d�finition}Un �nombre� est un entier relatif compris entre $-2^{31}+1$ et $2^{31}-1$, c'est-�-dire entre $-\numprint{2147483647}$ et $\numprint{2147483647}$. Tout nombre hors de cet intervalle provoque une erreur de compilation.

Lorsque \TeX{} s'attend � lire un nombre, il entre dans une phase de d�veloppement maximal. Dans les r�sidus de ce d�veloppement, il cherche tout d'abord une s�rie de signes optionnels de catcode 12 : �\verb|+|� et �\verb|-|�. Le signe du nombre final d�pendra de la parit� du nombre de signes �\verb|-|� lus au total. Ensuite, plusieurs cas peuvent se pr�senter :
\begin{enumerate}
       \item le nombre est explicitement �crit en

       \begin{itemize}[topsep=0pt]
               \item base 8 sous la forme \verb|'<signes>|;
               \item base 10 sous la forme \verb|<signes>|;
               \item base 16 sous la forme \verb|"<signes>|,
       \end{itemize}

       o� les \verb|<signes>| sont une suite de chiffres de catcode 12 allant de \verb|0| � \verb|7| pour la base 8, de \verb|0| � \verb|9| pour la base 10 et pour la base 16, de \verb|0| � \verb|9| auxquels s'ajoutent les lettres \emph{majuscules} de catcode 11 ou 12 allant de \verb|A| � \verb|F|.

       \TeX{} stoppe la lecture du nombre au premier token qui n'est pas un \verb|<signe>| valide. Si ce token est un espace, il sera absorb�. Le nombre lu comprend donc la plus longue s�rie de \verb|<signes>| valides possible;
       \item un � compteur � se pr�sente (nous verrons les compteurs plus loin). Le nombre qu'il contient est lu et la lecture du nombre est stopp�e;
       \item un � registre de dimension � se pr�sente. Dans ce cas, la dimension est convertie en entier (nous verrons comment plus loin) et la lecture du nombre s'ach�ve;
       \item une \idx{s�quence de contr�le} d�finie avec \idx\chardef pour les nombres compris entre 0 � 255 ou avec \idx\mathchardef pour ceux compris entre 0 � 32767 se pr�sente, le nombre correspondant est lu et la lecture du nombre est stopp�e;
       \item un nombre �crit sous la forme \verb|`<car>| ou \verb|`\<car>| se pr�sente, o� �\verb|`|� est l'apostrophe inverse. Le nombre lu est le code de caract�re de \verb|<car>|. Le \emph{d�veloppement maximal se poursuit} jusqu'au premier token non d�veloppable qui signe la fin de la lecture du nombre. \emph{Si ce token est un espace, il est absorb�}.
\end{enumerate}
\end{regle}

Plain-\TeX{} d�finit la \idx{s�quence de contr�le} \idx\z@ comme �tant un registre de dimension �gal � la dimension nulle \verb|0pt|. Cette \idx{s�quence de contr�le} est souvent employ�e en programmation, car elle pr�sente 3 avantages :

\begin{enumerate}
       \item elle est convertie en l'entier 0 lorsque \TeX{} lit un nombre entier;
       \item elle est la dimension \verb|0pt| lorsque \TeX{} lit une dimension;
       \item dans les deux cas pr�c�dents, elle stoppe la lecture et le d�veloppement maximal.
\end{enumerate}

La primitive \idx\number est d�veloppable et son 1-d�veloppement provoque un travail assez cons�quent : lecture du nombre selon la r�gle vue ci-dessus et conversion de ce nombre en base 10 sous la forme la plus simple en tokens de catcode 12. Par �forme la plus simple�, on entend que le signe du nombre n'est donn� que s'il est n�gatif et que les 0 inutiles de gauche sont supprim�s si le nombre �tait explicitement �crit.

Lorsque \idx\the est imm�diatement suivi d'un compteur, d'un registre de dimension ou d'une s�quence de contr�le d�finie avec  \idx\chardef ou \idx\mathchardef, elle se comporte comme \idx\number.

Les compteurs, les registres de dimensions et les s�quences de contr�le d�finies avec \idx\chardef ou \idx\mathchardef sont des repr�sentations \emph{internes} d'entiers qui n�cessitent une primitive d�veloppable (\idx\the ou \idx\number) pour obtenir les chiffres formant ce nombre en base 10. C'est donc une erreur que de les en d�pourvoir pour les afficher.

\subsection{Nombres romains}
Tout comme \idx\number et \idx\the sont capable de produire des nombres arabes, la primitive \idx\romannumeral produit des nombres romains.

\begin{regle}
La primitive \idx\romannumeral doit �tre suivie d'un \verb|<nombre>| valide.

Son 1-d�veloppement est
\begin{itemize}
       \item l'�criture en chiffres romains de catcode 12 si le \verb|<nombre>| est strictement positif;
       \item vide si le nombre est n�gatif ou nul.
\end{itemize}

Si le \verb|<nombre>| est sup�rieur � 1000, la lettre �\verb|m|� de catcode 12 sera produite autant de fois qu'il y a de milliers dans le nombre.
\end{regle}

Nous faisons fonctionner ici la primitive \idx\romannumeral en l'encadrant des caract�res �\verb|"|� pour mettre en �vidence que les espaces qui suivent les nombres disparaissent bien. V�rifions �galement que le d�veloppement maximal a bien lieu avec les macros \verb-\foo- et \verb-\bar- :

\showcode|a) "\romannumeral 27 "\quad�\idx*\romannumeral\idx*\quad�
b) "\romannumeral 4687 "\quad
c) "\romannumeral 0 "\quad% 0 donc d�veloppement vide
d) "\romannumeral -2014 "\quad% n�gatif donc d�veloppement vide
e) \def\foo{7}\def\bar{\foo}%
  "\romannumeral \foo\foo\bar"\quad% 777
f) "\romannumeral 1\bar8\foo"\quad% 1787
g) "\romannumeral 1\bar8 \foo"% 178 (stopp� par l'espace) puis 7�\idx*\quad\idx*\romannumeral�|

Remarquons la diff�rence entre les cas f et g o� le simple espace en plus apr�s �8� au cas g stoppe la lecture du nombre et le d�veloppement maximal. On constate que cet espace est absorb�, car aucun espace n'existe � l'affichage entre �\verb|clxxviii|� et �7�.

\subsection{Le d�veloppement de \texttt{\char`\\romannumeral}}\idx*[!d�veloppement|(]\romannumeral
La primitive \idx\romannumeral est tr�s int�ressante, car son 1-d�veloppement d�clenche un d�veloppement maximal dont on peut contr�ler la port�e. Surtout, ce d�veloppement maximal peut ne laisser aucune trace si le nombre que lit finalement \idx\romannumeral est n�gatif ou nul.

Si dans ce sch�ma

\begin{centrage}
       \small\fboxsep1pt
       \fboxrule0.4pt
       \verb-\romannumeral-\fbox{\fboxsep0pt \fcolorbox{gray!60}{gray!60}{\strut\kern2.5cm }$x$\textvisiblespace}
\end{centrage}

\begin{enumerate}
       \item la zone grise ne contient que des tokens purement d�veloppables dont le d�veloppement est vide;
       \item $x$ est un nombre n�gatif ou nul
\end{enumerate}

\noindent alors, 1-d�velopper \idx\romannumeral revient � d�velopper au maximum tous les tokens se trouvant dans la zone grise et � supprimer le nombre $x$ et l'espace qui le suit.

La zone encadr�e devient une zone de d�veloppement maximal dont la port�e est contr�l�e par le placement du nombre n�gatif ou nul $x$.

Certes, cela implique une contrainte forte : tous les tokens dans la zone grise doivent �tre purement d�veloppables et une fois ceci fait, ils ne doivent rien laisser. En pratique, cette zone grise contient des appels � des macros et des tests.
\grandsaut

Pour mettre en �vidence l'utilit� d'une telle structure, reprenons l'exercice de la page~\pageref{expsecond} o� l'on a vu que �\expsecond\verb-{<arg1>}{<arg2>}- devait se d�velopper 3 fois pour que le code effectivement dans la pile soit \verb-<arg1>{*arg2}- (l'�toile indique que le premier token de l'argument 2 est 1-d�velopp�). Nous avions calcul� qu'il fallait placer 7 \idx\expandafter devant \verb-\>- pour parvenir � nos fins :

\showcode/\long\def\>#1<{\detokenize{#1}}�\idx*\long\idx*\detokenize�
\def\swaparg#1#2{#2{#1}}��*\swaparg�
\def\expsecond#1#2{\expandafter\swaparg\expandafter{#2}{#1}}��*\expsecond�*\swaparg�
\def\X{Bonjour}
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
\>\expsecond\X\X<��*\expsecond�/

Avec \verb-\romannumeral-, un seul \verb|\expandafter| sera requis pour sauter \verb|\>| et provoquer le 1-d�veloppement de \verb-\romannumeral- qui va tout d�velopper au maximum et s'arr�ter au bon moment. Ce \emph{bon moment} sera juste avant le \verb|\X| observ� � l'affichage. Comme ce \verb|\X| est l'argument \verb|#2| de �\swaparg, un simple \verb*|0 |, plac� avant cet argument \verb|#2| stoppe le d�veloppement maximal initi� par \verb|\romannumeral| :

\showcode/\long\def\>#1<{\detokenize{#1}}�\idx*\long\idx*\detokenize�
\def\swaparg#1#2{0 #2{#1}}% le "0 " stoppe ici le d�veloppement maximal��*\swaparg�
\def\expsecond#1#2{\expandafter\swaparg\expandafter{#2}{#1}}��*\expsecond�*\swaparg�
\def\X{Bonjour}
\expandafter\>\romannumeral\expsecond\X\X<�\idx*\romannumeral�*\expsecond�/

\begin{exercice}
� quel autre endroit aurait-on pu placer �\verb*-0 -� pour que le d�veloppement se passe comme on le souhaite ?
\solution
On veut stopper la lecture du nombre juste avant l'argument \verb-#2- de la commande �\swaparg. Cet argument est l'argument \verb-#1- de la commande �\expsecond et il suffit donc de mettre �\verb*-0 -� au d�but du premier argument de �\expsecond lorsqu'elle est appel�e.

\showcode/\long\def\>#1<{\detokenize{#1}}�\idx*\long\idx*\detokenize�
\def\swaparg#1#2{#2{#1}}��*\swaparg�
\def\expsecond#1#2{\expandafter\swaparg\expandafter{#2}{#1}}��*\expsecond�*\swaparg�
\def\X{Bonjour}
\expandafter\>\romannumeral\expsecond{0 \X}\X<�\idx*\romannumeral�*\expsecond�/

Contrairement � celle de l'exemple pr�c�dent, cette m�thode pr�sente l'avantage de ne pas avoir � modifier les macros �\swaparg et �\expsecond.
\medbreak

On aurait donc remplacer \verb*|0 | par \idx\z@ avec l'avantage pour ce dernier de stopper la lecture du nombre sans avoir � ins�rer un espace :

\showcode/\long\def\>#1<{\detokenize{#1}}�\idx*\long\idx*\detokenize�
\def\X{Bonjour}
\catcode`\@=11
\expandafter\>\romannumeral\expsecond{\z@\X}{\X}<�\idx*\romannumeral\idx\z@�*\expsecond�
\catcode`\@=12 /
\end{exercice}\idx*{nombre}\idx*[!d�veloppement|)]\romannumeral

\section{Programmation d'une variable unidimensionnelle}
Finissons ce chapitre en programmant une � variable �, constitu�e de cellules qui auront chacune un nom et qui contiendront un code choisi par l'utilisateur. Il s'agit ici de copier les variables de type tableau (ou array) � une dimension qu'offrent la plupart des langages de programmation.

Supposons que l'on veuille d�finir la variable unidimensionnelle \verb-\foobar-. Pour d�finir la variable et remplir les cases dont les noms sont �\texttt 0�, �\texttt 1�, �\texttt 3� et �\texttt{toto}�, on doit pouvoir �crire :

\centrecode-\newunivar\foobar��*\newunivar�
\defunivar\foobar[0]{abcd}
\defunivar\foobar[1]{1 23}
\defunivar\foobar[3]{XY Z}
\defunivar\foobar[toto]{Bonjour}��*\defunivar�-

\noindent Et par la suite, il suffira que l'on �crive \verb-\foobar[0]- pour que le code �\verb|abcd|�, contenu dans la cellule �\verb|0|� soit restitu� et ex�cut�.
\grandsaut

Passons maintenant � la m�canique interne. Si la variable est �\verb|\foobar|�, d�cidons que le contenu des cellules sera stock� dans des s�quences de contr�le auxiliaires. Par exemple, le code de la cellule \verb|0| sera contenu dans la macro  \verb-\-\boxtoken{\foobar[0]}. Autrement dit, le \emph{nom} de la macro doit �tre constitu� des 10 caract�res (inoffensifs) \boxtoken{ \unskip\textbackslash}, \boxtoken f, \boxtoken o, \boxtoken o, \boxtoken b, \boxtoken a, \boxtoken r, \boxtoken{[}, \boxtoken 0 et \boxtoken]. Pour former un tel nom, nous ferons appel � la paire \idx\csname\linebreak[1]\verb-...-\linebreak[1]\idx\endcsname.

L'ordre �\verb-\newunivar\foobar-� doit donc d�finir la macro \verb-\foobar- de cette fa�on :

\centrecode-\def\foobar[#1]{\csname\string\foobar[#1]\endcsname}-\idx*\string

Si on place ce texte de remplacement dans la d�finition de �\newunivar, il suffit de remplacer \verb|\foobar| par l'argument \verb|#1| de �\newunivar et de doubler les �\verb|#|�. La macro �\newunivar sera donc d�finie ainsi :

\centrecode-\def\newunivar#1{\def#1[##1]{\csname\string#1[##1]\endcsname}}-\idx*\string�*\newunivar

\noindent On pourra ainsi appeler par la suite \verb-\foobar[0]- qui se 2-d�veloppera en la macro \verb-\-\boxtoken{\foobar[0]} tout en offrant la protection, au cas o� la cellule n'a pas �t� d�finie, que la paire \verb-\csname-\linebreak[1]\verb-...-\linebreak[1]\verb-\endcsname- g�n�re l'inoffensif \idx\relax. Aucune erreur de compilation ne sera donc provoqu�e en cas d'appel � une cellule non d�finie.

Pour la macro �\defunivar\verb-\<macro>[<nom>]-, un \idx\expandafter forcera la formation de la \idx{s�quence de contr�le} avant que \verb-\def-, qui proc�de l'assignation, ne voie cette \idx{s�quence de contr�le}. Par cons�quent, �\defunivar\verb-\foo[0]- doit avoir le texte de remplacement suivant :

\centrecode-\expandafter\def\csname\string\foo[0]\endcsname-\idx*\string�*\defunivar

\noindent Et donc, �\defunivar doit �tre d�finie comme suit :

\centrecode-\def\defunivar#1[#2]{\expandafter\def\csname\string#1[#2]\endcsname}-\idx*\string�*\defunivar

\noindent ou encore, en utilisant �\defname

\centrecode-\def\defunivar#1[#2]{\defname{\string#1[#2]}}-

\noindent Il est inutile de lire l'argument du \verb|\def| qui est le contenu de la cellule. En effet, comme on l'a d�j� vu � la page~\pageref{argument.def}, lire cet argument serait redondant puisqu'il faudrait le placer entre accolades � la fin du texte de remplacement de �\defunivar. Voici donc comment proc�der :

\showcode/\def\newunivar#1{\def#1[##1]{\csname\string#1[##1]\endcsname}}��*\newunivar\idx*\string�
\def\defunivar#1[#2]{\defname{\string#1[#2]}}��*\defunivar\idx*\string�*\defname�
\newunivar\foobar��*\newunivar�
\defunivar\foobar[0]{abcd}
\defunivar\foobar[1]{1 23}
\defunivar\foobar[3]{XY Z}��*\defunivar�
Cellule 0 : \foobar[0]\par
Cellule 1 : \foobar[1]\par
Cellule 2 : \foobar[2]\par% cellule non d�finie : \foobar[2] donne \relax
Cellule 3 : \foobar[3]\bigbreak

\newunivar\client��*\newunivar�
\defunivar\client[nom]{M. Raymond {\sc  Tartempion}}�\idx*\sc�
\defunivar\client[adr]{5 rue de la paix}
\defunivar\client[cod_post]{75000}
\defunivar\client[ville]{Paris}��*\defunivar�
% fin des d�finitions, affichage de l'adresse :
\client[nom]\par
\client[adr]\par
\client[cod_post] \client[ville]/

On remarque que la programmation de cette variable unidimensionnelle est ici, gr�ce � la richesse et la puissance des instructions de \TeX{}, relativement facile et extr�mement concise puisqu'elle tient en deux lignes !

\begin{exercice}
Comment modifier les macros �\newunivar et �\defunivar vues pr�c�demment pour que les cellules ne soient pas stock�es dans la macro \verb-\-\boxtoken{\foobar[0]} mais dans la macro \verb-\-\boxtoken{foobar@0} ?
\solution
Faisons la supposition fond�e que \idx\escapechar d�finit �\verb|\|� comme \idx{caract�re d'�chappement}. Lorsque \idx\string est d�velopp�e � l'int�rieur de \verb-\csname-\linebreak[1]\verb-...-\linebreak[1]\verb-\endcsname-, il con\-vertit le token \boxtoken{\foobar} en 7 tokens de catcode 12\idx*{catcode!12 (autre)} qui sont \boxtoken{ \unskip\textbackslash} \boxtoken{f} \boxtoken{o} \boxtoken{o} \boxtoken{b} \boxtoken{a} \boxtoken{r}. Il suffit de manger le premier token \boxtoken{ \unskip\textbackslash} avec un �\gobone en ayant pris soin de 1-d�velopper \idx\string avant que �\gobone n'entre en action :

\centrecode-\def\newunivar#1{%��*\newunivar�
       \def#1[##1]{\csname\expandafter\gobone\string#1@##1\endcsname}}�\idx*\string�*\gobone�
\def\defunivar#1[#2]{%��*\defunivar�
       \defname{\expandafter\gobone\string#1@#2}}�\idx*\string�*\gobone�*\defname�-
\end{exercice}

\begin{center}
$\star$\par
$\star\quad\star$
\end{center}

Voici la fin de cette longue et difficile partie o�, en nous int�ressant aux commandes, nous avons d�couvert comment \TeX{} fonctionne. Pour r�sumer � l'extr�me, \TeX{} est un langage de macros et donc, se comporte comme une machine qui remplace du code par du code jusqu'� arriver � des tokens non d�veloppables qui seront �ex�cut�s� (des primitives, des caract�res ordinaires de catcode 10, 11 ou 12 qui seront affich�s ou des caract�res rev�tant des propri�t�s li�es � leur catcode, comme \verb|$|).

Si l'on entre un peu plus dans les d�tails et en r�sumant ce qui a �t� dit, voici comment on peut se repr�senter le fonctionnement de \TeX{} : comme nous l'avons vu � la premi�re partie, le code \TeX{} est constitu� de cases chacune form�e d'un \idx{octet} pour les \idx*{moteur!8 bits}moteurs 8 bits ou par une s�quence d'octets codant un caract�re \utf pour les moteurs \utf.\idx*{moteur!utf8} Lorsqu'ils sont transform�s en tokens lorsque \TeX{} les lit, chacun de ces caract�res ob�it � des r�gles particuli�res propres � leurs cat�gories. Voici les cas particuliers qui sont transform�s lors de la lecture :

\begin{itemize}
       \item lorsque des lettres sont pr�c�d�es du \idx{caract�re d'�chappement} �\verb-\-� de catcode 0\idx*{catcode!0 (caract�re d'�chappement)}, le tout ne forme qu'un seul token, une \idx{s�quence de contr�le};
       \item lorsqu'un \idx{espace} (catcode \number\catcode`\ )\idx*{catcode!10 (espace)} dans le code est suivi d'autres espaces\idx*{espace!cons�cutifs}, les autres espaces sont ignor�s;
       \item un seul retour charriot \verbidx[ (retour charriot)]{^^M} (catcode 5) est compris comme �tant un espace;
       \item deux retours charriots cons�cutifs sont �quivalents au token \idx\par;
       \item deux caract�res identiques de catcode \number\catcode`\^\idx*{catcode!7 (exposant)} cons�cutifs (comme �\verbidx{^^}�) sont convertis en un caract�re selon les r�gles expos�es � la 1\iere{} partie;
       \item le caract�re �\cidx\%� (catcode \number\catcode`\%) ainsi que tous les caract�res jusqu'au retour charriot suivant sont ignor�s.
\end{itemize}

Ainsi, on peut consid�rer le code \TeX{} comme �tant des caract�res �crits les uns � la suite des autres comme s'ils �taient sur un ruban et, apr�s leur lecture, ces caract�res sont transform�s en de la mati�re assimilable par \TeX{}, les tokens. \TeX{} fonctionne � la mani�re d'une t�te de lecture qui se d�place toujours lin�airement de gauche � droite sur le ruban o� est �crit le code. Voici, comment on peut se repr�senter sch�matiquement le fonctionnement de \TeX{} :

\begin{enumerate}
       \item lire un token : utiliser en priorit� les tokens stock�s dans la pile d'entr�e si elle n'est pas vide et dans le cas contraire, construire le token � partir des caract�res du code source en appliquant les r�gles de lecture du code en vigueur � ce moment-l�.

       Si ce token lu requiert la lecture d'autres tokens (lecture d'un nombre, cas d'une macro � plusieurs arguments, cas de \verb|\def| qui doit �tre suivi d'une macro, d'un texte de param�tre et d'un texte de remplacement, etc.), recommencer en 1 jusqu'� ce que les tokens requis soient lus;
       \item figer les catcodes de tous les tokens lus et les stocker en m�moire;
       \begin{enumerate}
       \item si ce qui vient d'�tre lu n'est pas d�veloppable, ex�cuter l'action que commande le tout;
       \item sinon, 1-d�velopper le premier token et ins�rer devant la t�te de lecture (dans la \idx{pile d'entr�e}) ce qui en r�sulte;
       \end{enumerate}
       \item retourner en 1.
\end{enumerate}

Lorsque \TeX{} est en phase de d�veloppement et si \verb|\expandfter| est la primitive � d�velopper, convenons que 0 est la position de cet \verb|\expandafter| dans la liste des tokens � lire. Lorsque \verb|\expandafter| est d�velopp�, la t�te de lecture de \TeX{} a la capacit�, sans bouger de place, de �d�tacher� une �t�te de d�veloppement�. Celle-ci, en se d�solidarisant de la t�te de lecture, ira 1-d�velopper le token se trouvant plus loin dans le code � la position 2 et suivra �ventuellement les ordres de d�veloppement que son 1-d�veloppement implique. Une fois qu'il n'y a plus d'ordre de d�veloppement � suivre, la t�te de d�veloppement revient sur la t�te de lecture qui reprend son travail o� elle l'avait laiss� et tiendra compte, dans le futur, des d�veloppements effectu�s par sa t�te de d�veloppement.
\grandsaut

On peut donc �noncer que le fonctionnement de \TeX{} s'apparente � celui d'une �\idx*{Turing (machine)}machine de Turing�.\idx*[|)]{d�veloppement}
%|                                                                            |
%|                                Fin partie 2                                |
%|____________________________________________________________________________|

% ____________________________________________________________________________
%|                                                                            |
%|                                  Partie 3                                  |
%|                                                                            |
\defpartcomment{\lettrine[lines=3,slope=4pt,nindent=0pt]{\libertineInitialGlyph{A}}{\kern -5pt pr�s} avoir abord� la plus grosse partie des sp�cificit�s de \TeX{}, nous pouvons entrer dans le vif du sujet avec de la programmation non lin�aire. Aucun algorithme complexe ne sera abord� dans cette partie, bien au contraire, nous nous en tiendrons aux plus �l�mentaires et aux plus passepartouts. Malgr� leur simplicit�, ils sont n�anmoins difficiles � cause des sp�cificit�s du langage \TeX{}.}

\part{Structures de contr�le et r�cursivit�}
\chapter{Les outils de programmation de \TeX}
Le langage \TeX{} a �t� dot� des structures de contr�les n�cessaires pour �laborer n'importe quel algorithme, aussi compliqu� soit-il. � ce titre, c'est donc un langage \emph{complet}\idx*{langage complet}. Bien s�r, il ne viendrait � l'id�e de personne de coder en \TeX{} un d�compresseur zip ou un algorithme de jeu d'�checs\footnote{Il faut tout de m�me signaler une r�cente extension appel�e � reverxii � pour \TeX{} qui joue au jeu d'Othello et qui tient en moins de 1000 octets ! Cette tr�s faible taille tient au fait que l'auteur a utilis� toutes les astuces \TeX{}iennes (programmation de caract�res actifs notamment) pour que la taille soit la plus petite possible, au prix d'une lisibilit� nulle � un tel point qu'il est presque impossible de dire s'il s'agit de code \TeX{} ou pas !\par Le programme comporte une intelligence artificielle qui, bien que loin d'�tre redoutable, peut tenir t�te � un joueur d�butant.} ! Dans le monde de \TeX{}, le mot � compilation � signifie � traduction de la totalit� code source en document affichable �. En \TeX{}, lorsqu'on parle de programmation, ce mot devient ambigu, car dans le monde de la programmation, � compilation� signifie � transformation du code source en code ex�cutable �, le fichier binaire ex�cutable obtenu �tant d'une grande rapidit�. Ce qu'il faut comprendre est que le langage \TeX{} est \emph{interpr�t�}, c'est-�-dire � ex�cut� au fur et � mesure � lors de la compilation ce qui le rend lent !
\grandsaut

Les principales structures de contr�le dont \TeX{} est dot� sont les suivantes :

\begin{itemize}
       \item l'assignation, c'est-�-dire la possibilit� de stocker des informations dans des � registres � (le mot � variables � est plus couramment utilis� dans d'autres langages), qui sont en quelque sorte des endroits de la m�moire accessibles et lisibles facilement. En \TeX{}, les structures les plus couramment utilis�es capables de stocker de l'information sont les suivants :
       \begin{itemize}
               \item les s�quences de contr�le;
               \item les registres de tokens;
               \item les registres d'entiers ou � compteurs � qui accueillent les entiers et sont dot�s des 4 op�rations o� la division n'est possible que par un entier, �tant entendu que cette division donne la partie enti�re;
               \item les registres de dimensions stockent des longueurs et qui permettent, sous certaines r�serves que nous verrons, de manipuler des nombres d�cimaux. Les 4 op�rations sont disponibles, mais la division n'est possible que par un \emph{entier};
               \item les registres de boites qui stockent un contenu arbitraire sous forme affichable, mais il n'est plus possible d'acc�der au code qui a g�n�r� ce contenu.
       \end{itemize}
       \item les tests ;
       \item la \idx{r�cursivit�}, c'est-�-dire la possibilit� pour une macro de s'appeler elle-m�me, que ce soit directement ou par l'interm�diaire d'une ou plusieurs autres macros ;
       \item la localit�, c'est-�-dire la possibilit� de d�finir une zone o� les assignations resteront valables dans cette zone pour �tre d�truites une fois sorti de cette zone, tout en permettant de proc�der � des assignations \emph{globales} qui survivent une fois que la zone est ferm�e ;
       \item la possibilit� d'�crire dans un fichier, c'est-�-dire d'y stocker des \emph{caract�res};
       \item la possibilit� de lire les caract�res stock�s dans un fichier.
\end{itemize}

Et c'est � peu pr�s tout ! Cette liste est \emph{minimaliste} et n'a rien � voir le pl�thore de moyens que propose un langage de programmation actuel. Pour faire une comparaison dans les moyens simples et basiques, il n'y a par exemple, aucune structure de boucle (for, loop, while, etc.). Ni de � variables � de type �volu� comme les tableaux � plusieurs dimensions par exemple. Aucune trace non plus d'op�rations scientifiques. Mais qu'� cela ne tienne, les structures �nonc�es ci-dessus sont bien suffisantes pour en programmer soi-m�me. Il faut s'y habituer, en \TeX{}, on ne dispose que du strict minimum et bien souvent, on doit construire soi-m�me des structures de contr�le plus �volu�es comme les boucles. La plupart du temps avec \TeX, tout est question d'assignations, de lecture raisonn�e d'arguments, de comparaison, de d�veloppement et de r�cursivit�. Pour autant que �a soit p�nible au d�but, en contrepartie, c'est extr�mement souple puisqu'on peut b�tir des boucles sur mesure. C'est ce que nous allons apprendre � faire dans cette partie en �tudiant plus sp�cialement les tests et la r�cursivit�.

Mais avant de les aborder, il nous faut revenir aux nombres entiers et comprendre comment \TeX{} calcule.

\chapter{\TeX{} et les entiers}\idx*[|(]{nombre}%
S'il y a bien un domaine o� \TeX{} n'excelle pas, c'est celui du calcul. On ne pourrait lui en vouloir puisque, con�u pour composer du texte, il n'�tait pas n�cessaire de le doter de puissants outils de calcul. Mais depuis que \TeX{} a �t� �crit, beaucoup de temps s'est �coul� � l'�chelle informatique et d�sormais, tout langage embarque pl�thore d'outils de calcul. Par cons�quent, un programmeur habitu� � ces outils ressent � un moment ou � un autre une l�gitime frustration envers \TeX{} qui ne les propose pas. Voyons tout de m�me ce que \TeX{} offre en mati�re de calculs arithm�tiques.

\section{L'arithm�tique \TeX{}ienne}
\subsection{Les entiers}
\idx*[|(]{compteur}\TeX{} manipule des entiers sign�s sur $32$ bits. Ils sont donc compris entre $-2^{31}+1$ et $2^{31}-1$ c'est-�-dire entre $-\numprint{2147483647}$ et $\numprint{2147483647}$. Ces entiers sont stock�s dans des registres sp�ciaux appel�s � compteurs �. 256 de ces registres sont disponibles avec \TeX{} et $\numprint{65536}$ avec $\varepsilon$\TeX{}. Ainsi, \verb|\count42| fait r�f�rence au compteur \no42. Contrairement aux registres de tokens avec \idx\toks\verb|0|, aucune convention n'existe quant � un compteur portant un num�ro sp�cial qui serait non utilis� et qui servirait de � compteur brouillon �.

\TeX{} met aussi � disposition la primitive \idx\countdef, qui ressemble � \idx\chardef ou \idx\toksdef. Par exemple, �crire

\centrecode-\countdef\foo=42-\idx*\countdef

\noindent rend \verb|\foo| �quivalent � \verb|\count42| de telle sorte que le registre \no42 peut �tre d�sign� par la \idx{s�quence de contr�le} \verb|\foo|. L'�quivalence dont il est question ici ressemble � celle de \idx\let en ce sens que \verb|\foo| n'est pas d�veloppable et n'a pas de texte de remplacement mais \emph{sera} \verb|\count42|.

Comme pour les registres de tokens avec \idx\toksdef, plain-\TeX{} fournit une macro \idx\newcount qui, suivie d'une \verb-\<macro>-, permet d'allouer un compteur pour y faire ensuite r�f�rence avec une macro plut�t que par un num�ro. La macro \idx\newcount se charge de trouver le num�ro du prochain registre de compteur libre. Si par exemple, on �crit \verb-\newcount\foo- et si 89 est le num�ro du prochain registre libre, alors la macro \idx\newcount proc�derait � l'assignation suivante :

\centrecode-\global\countdef\foo=89-\idx*\global\idx*\countdef

\noindent La primitive \idx\global, plac�e devant l'assignation, rend celle-ci globale : on ne peut donc pas allouer localement un registre de compteur qui serait ensuite lib�r� apr�s la sortie d'un groupe\footnote{Bien �videmment, mobiliser un compteur localement est possible, mais il faudrait �crire une nouvelle macro le permettant. Ceci est fait par le \idx[!etex]{package} \texttt{etex.sty} pour \LaTeX{} qui, entre autres fonctionnalit�s, fournit une macro \texttt{\char`\\loccount\char`\\\codeelement{macro}} par laquelle le compteur est d�fini de fa�on \emph{locale}.}.

\begin{regle}
Un compteur a vocation � contenir un nombre entier de $-2^{31}+1$ � $2^{31}-1$. On y fait r�f�rence par

\centrecode-\count<nombre>-

Il est aussi possible d'utiliser la commande

\centrecode-\newcount\<macro>-

qui fait le n�cessaire pour lier la \verb|\<macro>| au prochain num�ro de compteur non utilis�. Par la suite, la \verb|\<macro>| se comporte exactement comme \idx\count\verb|<nombre>|. Comme les registres de tokens, les \verb|<compteurs>| peuvent donc indiff�remment �tre d�sign�s selon ces deux possibilit�s.
\grandsaut

Pour assigner un \verb|<entier>| (voir la d�finition d'un entier � la page~\pageref{definition.entier}) � un compteur, il faut �crire\idx*{assignation!compteur}

\centrecode-<compteur>= <entier>-

\noindent o� le signe \verb-=- ainsi que l'espace qui le suit sont facultatifs.
\end{regle}

Rappelons que pour \emph{afficher} la valeur du compteur, nous ne pouvons pas �crire \verb|<compteur>| dans le code sans risquer de provoquer une erreur de compilation. En effet, \TeX{} attendrait une assignation qui commence de cette fa�on et si ce \verb|<compteur>| n'�tait pas suivi d'un \verb|<nombre>|, \TeX{} se plaindrait d'un �\texttt{Missing number, treated as zero} �. Un compteur �tant une repr�sentation interne d'un entier, pour \emph{afficher} sa valeur, il faut traduire cette repr�sentation interne en caract�res affichables, et faire pr�c�der le \verb|<compteur>| de \idx\the, \idx\number ou \idx\romannumeral :

\showcode/\newcount\foo \newcount\bar�\idx*\newcount�
\foo=42 \bar=\foo \string\bar\ vaut : \the\bar \par�\idx*\string\idx*\the�
\bar=\foo57 \string\bar\ vaut : \number\bar\par�\defline\aaa\idx*\number�
\bar=2014 \string\bar\ vaut : \romannumeral\bar�\idx*\romannumeral\idx*\string�/

\noindent La ligne \no\aaa{} montre que les caract�res �\verb|57|� ne sont pas pris en compte pour l'affectation. Comme cela est dit � la page~\pageref{definition.entier}, si le \verb|<nombre>| que \TeX{} lit est un registre de compteur, le nombre qu'il contient est lu, et la lecture du nombre s'arr�te (laissant ici �\verb|57|� hors du nombre pris en compte).

\begin{exercice}
\Qu e fait le code suivant ?

\centrecode-\newcount\foo
\newcount\bar
\foo=57
\bar=9\foo8\relax-

\solution
Tout d'abord, deux compteurs sont cr��s. Le nombre \verb|57| est affect� au compteur \verb|\foo|. Puis, � la derni�re ligne, � droite de \verb|\bar=|, l'entier lu est \verb|9| car la lecture du nombre s'arr�te sur \verb|\foo| qui n'est pas d�veloppable et n'est pas un chiffre.

Le compteur \verb|\bar| vaut donc 9 et ce qui est � la suite �\verb|\foo8\relax|� est une affectation qui rendrait le compteur \verb|\foo| �gal � 8, �crasant la valeur \verb|57| qu'il avait auparavant. Le code propos� fait 3 assignations et ne produit aucun affichage.

� la derni�re ligne, si nous avions voulu assigner 9578 au compteur \verb|\bar| (o� 57 est la valeur du compteur \verb|\foo|), il aurait fallu �crire  :

\centrecode-\bar=9\number\foo8\relax-

de telle sorte que le d�veloppement mis en  place pour la lecture du nombre convertisse \idx\number\verb|\foo| en caract�res valides pour un \verb|<nombre>|.
\end{exercice}

\subsection{Les op�rations}\idx*[|(]{op�rations arithm�tiques}
Venons-en aux op�rations arithm�tiques � notre disposition. Celles-ci op�rent sur des compteurs, c'est-�-dire qu'il n'est pas possible de faire des op�rations sur des nombres explicitement �crits en chiffres.

\begin{regle}
Dans les lignes ci-dessous, \verb|<n>| est un nombre entier au sens de \TeX{} :

\begin{itemize}
       \item \idx\advance\verb-<compteur> by <n>- : ajoute \verb-<n>- au \verb-<compteur>-;
       \item \idx\multiply\verb-<compteur> by <n>-  : multiplie le \verb-<compteur>- par \verb-<n>-;
       \item \idx\divide\verb-<compteur> by <n>- : divise le \verb-<compteur>- par \verb-<n>- en lui assignant la troncature � l'unit� si le r�sultat de la division n'est pas entier.
\end{itemize}

Dans tous les cas, le mot �\verb-by-� et l'espace qui le suit sont facultatifs.
\end{regle}

Avec ces trois op�rations, il est possible de programmer une macro \verb-\fonction- dont l'argument est un entier $n$ et qui calcule et affiche la valeur de $(3n-4)^2$. Le principe est d'assigner l'entier $n$ � un compteur et effectuer les op�rations sur ce compteur (le multiplier par 3, lui ajouter $-4$, puis le multiplier par lui-m�me) pour l'afficher ensuite :

\showcode/\newcount\foo�\idx*\newcount�
\def\fonction#1{%
 \foo=#1 % assigne l'entier #1 au compteur puis
 \multiply\foo3 % multiplie par 3�\idx*\multiply�
 \advance\foo-4 % soustrait 4�\idx*\advance�
 \multiply\foo\foo% �l�ve au carr� (lmultiplie \foo par lui m�me)�\idx*\multiply�
 \number\foo% enfin, afficher le r�sultat�\idx*\number�
}
a) \fonction5\qquad b) \fonction{-13}/

La macro donne bien les r�sultats attendus, mais l'inconv�nient est qu'elle n�cessite un compteur et surtout qu'elle n'est pas purement d�veloppable. En effet, si nous �crivons \verb-\edef\bar{\fonction5}-, la macro \verb-\bar- n'aura pas 121 comme texte de remplacement. La raison est que le texte de remplacement de \verb-\fonction- contient des primitives qui ne se d�veloppent pas (\idx\multiply, \idx\advance) et la s�quence de contr�le \verb|\foo| qui n'est pas d�veloppable non plus. Il s'agit ici d'un cas qui illustre la fondamentale diff�rence entre � affichage produit par une macro apr�s ex�cution � et � texte de remplacement de cette macro �. Ce n'est pas parce que �\verb|\fonction5|� affiche \verb|121| que tout se passe comme si �\verb|\fonction5|� �tait �quivalent (m�me apr�s d�veloppement) aux caract�res \verb|121|. Nous pouvons le constater sur cet exemple :

\showcode/\newcount\foo�\idx*\newcount�
\def\fonction#1{%
 \foo=#1 \multiply\foo3 \advance\foo-4 \multiply\foo\foo�\defline\aaa\idx*\multiply\idx*\advance�
 \number\foo}�\idx*\number�
\edef\bar{\fonction{5}}%
a) Signification : \meaning\bar\par�\idx*\meaning�
b) Ex�cution : \bar�\defline\bbb�/

Pourquoi obtenons-nous \verb|0| lorsque \verb|\bar| est ex�cut�e ? Parce que le code contenu dans \verb|\bar| (et affich� au cas a) effectue dans un premier temps les calculs sur le compteur \verb|\foo|, mais au lieu d'afficher le ce que contient ce compteur, elle affiche 0, qui est le r�sidu du d�veloppement de \idx\number\verb|\foo|.
\grandsaut

Non contente de cr�er une macro non purement d�veloppable, la m�thode pr�c�dente peut rapidement rendre l'enchainement des op�rations lourd, fastidieux et peu lisible, pour peu que les expressions � calculer soient plus complexes. En l'�tat de \TeX{} tel qu'il a �t� �crit par \idx*{Knuth Donald}D.~\textsc{Knuth}, il n'est pas possible de s'y prendre autrement. Heureusement, avec le moteur \idx\eTeX\idx*{moteur!etex}, une autre alternative est possible.

\subsection{La primitive \texttt{\char`\\numexpr}}\idx*[|(]{\numexpr}
Pour les entiers, la primitive \idx\numexpr\label{numexpr} permet d'effectuer un enchainement d'op�rations arithm�tiques via une �criture math�matique en notation infix�e o� les priorit�s arithm�tiques habituelles sont respect�es. Dans ces expressions, les espaces sont ignor�s, les signes d'op�rations sont \verb|+|, \verb|-|, \verb|*| et \verb|/| et des entiers explicitement �crits en chiffres peuvent y figurer. Pour la division, la seule diff�rence avec la division \TeX ienne r�side dans le fait qu'elle donne \emph{l'entier le plus proche} au lieu de \emph{la troncature}\idx*{op�rations arithm�tiques!troncature (division)}. Les expressions aussi contenir des parenth�ses.

\begin{regle}
La primitive \idx\numexpr permet de calculer des enchainements d'op�rations sur les entiers, pris au sens de la d�finition de la page~\pageref{definition.entier}. Elle doit �tre suivie d'une expression arithm�tique o� les espaces sont ignor�s, les signes op�ratoires sont \verb|+|, \verb|-|, \verb|*|, \verb|/| et o� les parenth�ses sont admises .

Elle cherche � �valuer ce qui la suit en amor�ant un d�veloppement maximal jusqu'� rencontrer un token qui ne peut figurer dans une expression arithm�tique. Si l'expression arithm�tique est suivie d'un \idx\relax, alors ce \idx\relax est mang� par \idx\numexpr. Ceci constitue une sp�cificit� de la primitive \texttt{\string\numexpr} puisqu'avec \TeX, seuls les \emph{espaces} sont mang�s apr�s les nombres. C'est donc une excellente habitude de faire suivre une expression arithm�tique �valu�e par \idx\numexpr d'un \idx\relax.

La structure

\centrecode-\numexpr<expression arithm�tique>\relax>-

est un entier au sens de \TeX{}, mais un peu comme l'est un compteur, c'est une repr�sentation \emph{interne} d'un entier et donc, pour l'afficher, il faut recourir � une primitive qui transforme la repr�sentation interne en caract�res affichables telle que \idx\the, \idx\number ou \idx\romannumeral.
\end{regle}

L'exemple suivant montre comment, avec \idx\number, on peut afficher une expression �valu�e par \idx\numexpr :

\showcode|a) \number\numexpr2+3*4\relax\qquad�\idx*\number\idx*\numexpr�
b) \romannumeral\numexpr2*3\relax\qquad�\idx*\romannumeral�
c) \number\numexpr(6-2*4)*(1-(2-6))\relax\qquad
d) \number\numexpr7/4\relax\qquad %7/4 vaut 1,75
e) \edef\foo{\number\numexpr2+3*4\relax}\meaning\foo�\idx*\meaning�|

Une expression �valu�e par \idx\numexpr peut contenir une sous-expression, elle-m�me �valu�e par un autre \idx\numexpr. Voici comment calculer 3*(1+2*5)+2, en �valuant l'expression entre parenth�ses avec un \idx\numexpr imbriqu� dans l'expression � calculer et en prenant soin de stopper sa port�e par un \idx\relax :

\showcode/\number\numexpr3*\numexpr1+2*5\relax+2\relax/

L'emploi de \idx\numexpr peut rendre la macro \verb-\fonction- vue pr�c�demment \emph{purement d�veloppable} :

\showcode/\def\fonction#1{\number\numexpr(3*#1-4)*(3*#1-4)\relax}�\idx*\number\idx*\numexpr�
a) \fonction5\qquad
b) \fonction{-13}\qquad
c) \edef\bar{\fonction5}\meaning\bar�\idx*\meaning�/

\begin{exercice}
Dans le code ci-dessus, l'expression �\verb|3*#1-4|� est �valu�e \emph{deux} fois, ce qui est inutile et consommateur de temps. Comment modifier le code pour qu'elle ne soit �valu�e qu'une seule fois ?
\solution
L'id�e est de provoquer le calcul de �\verb|3*#1-4|� et passer le r�sultat � une macro auxiliaire \verb|\carre| qui affichera le carr� de son argument:

\showcode/\def\fonction#1{\exparg\carre{\number\numexpr3*#1-4\relax}}�\idx*\numexpr�*\exparg�
\def\carre#1{\number\numexpr#1*#1\relax}�\idx*\number\idx*\numexpr�
a) \fonction{5}\qquad
b) \fonction{-13}\qquad
c) \edef\bar{\fonction5}\meaning\bar�\idx*\meaning�/

Ici, la macro �\exparg 1-d�veloppe et force le calcul de \verb|\number\numexpr3*#1-4\relax| en un nombre sign� explicitement �crit, qui est transmis � la macro \verb|\carre| qui se charge de le multiplier par lui-m�me.
\end{exercice}

Il est parfois g�nant que la primitive de \TeX{} \idx\divide sur les compteurs et la division �\verb|/|� de \idx\numexpr ne donnent pas les m�mes r�sultats. En effet, cela rompt la coh�rence qui existe entre les trois autres op�rations. Comment r�concilier les deux et faire en sorte d'inventer une division pour \idx\eTeX{} qui donne aussi la troncature ? Pour cela, il existe une formule g�n�rale. Si $x$ et $y$ sont deux entiers \emph{positifs}, si �\verb|/|� repr�sente la division donnant l'entier le plus proche (la division de \idx\numexpr donc), la troncature du quotient de $x$ par $y$ est

\[(x-(y-1)/2)/y\]

� l'aide de \idx\numexpr, il est facile de programmer une macro \verb|\truncdiv{|$x$\verb|}{|$y$\verb|}| qui calcule la troncature du quotient de $x$ par $y$. Le r�sultat est donn� sous la forme d'un entier \emph{non explicite}, c'est-�-dire qu'il faut \idx\number pour transformer cet entier en nombre affichable :

\showcode|\def\truncdiv#1#2{\numexpr(#1-(#2-1)/2)/#2\relax}�\idx*\numexpr�*\truncdiv\idx*\number�
8/3 :
a) \number\truncdiv83\qquad      % doit donner 2
b) \number\truncdiv{-8}3\qquad   % doit donner -2
c) \number\truncdiv8{-3}\qquad   % doit donner -2
d) \number\truncdiv{-8}{-3}\par  % doit donner 2
4/3 :
e) \number\truncdiv43\qquad      % doit donner 1
f) \number\truncdiv{-4}3\qquad   % doit donner -1
g) \number\truncdiv4{-3}\qquad   % doit donner -1
h) \number\truncdiv{-4}{-3}      % doit donner 1��*\truncdiv�|

La macro donne bien des r�sultats erron�s lorsque les nombres sont de signes contraires. Nous verrons au prochain chapitre comment la modifier pour que le r�sultat soit correct dans tous les cas.

Bien entendu, �\truncdiv peut �tre �crite dans une expression num�rique �valu�e par \idx\numexpr puisque les \idx\numexpr peuvent �tre imbriqu�s sous r�serve que les \idx\numexpr internes aient leur port�e limit�e par \idx\relax, ce qui est le cas ici.\idx*[|)]{op�rations arithm�tiques}\idx*[|)]{\numexpr}

\section{Le test \texttt{\textbackslash{}ifnum}}\label{ifnum}\tidx*[|(]{ifnum}%
Le test \tidx{ifnum} est le premier test abord� puisqu'il a un �troit rapport avec le chapitre en cours sur les nombres entiers. Il est aussi l'un des plus fr�quents.  Il n'est cependant qu'un test parmi beaucoup d'autres et avant de s'int�resser plus en d�tail � \tidx{ifnum}, un peu de th�orie sur les tests de \TeX{} doit �tre abord�e.

\subsection{Structure des tests}

\begin{regle}
Les tests de \TeX{} sont ex�cut�s par des primitives qui ob�issent aux contraintes suivantes :

\begin{enumerate}
       \item le nom des primitives ex�cutant un test commence par les lettres �\verb|if|� suivies d'autres lettres not�es \verb|<test>| d�terminant de quel test il s'agit;
       \item si \verb|\if<test>| est une primitive ex�cutant un test sur ses \verb|<arguments>|, sa structure est la suivante :

\centrecode-\if<test><arguments>
       <code ex�cut� si le test est vrai>
\else
       <code ex�cut� si le test est faux>
\fi-

       La branche entre \tidx{else} et \tidx{fi} est facultative et donc, un test peut �galement avoir la structure suivante :

\centrecode-\if<test><arguments>
       <code ex�cut� si le test est vrai>
\fi-
\end{enumerate}

Au lieu de \tidx{else} et \tidx{fi}, on peut mettre toute s�quence de contr�le rendue \idx\let-�gale � \tidx{else} ou \tidx{fi}.

Les tests et les primitives \tidx{else} et \tidx{fi} sont d�veloppables.
\end{regle}

Les codes ex�cut�s selon l'issue du test peuvent aussi contenir des tests sans que \TeX{} ne s'y perde dans les appariements entre les primitives \verb|\if<test>| et leur \tidx{else} ou \tidx{fi}. En effet, un peu comme le compteur d'accolades, \TeX{} est dot� d'un compteur interne d'imbrication de tests qui assure que chaque primitive de test est correctement appari�e avec le bon \tidx{else} ou \tidx{fi}.

Il est en outre primordial de comprendre qu'� l'occasion d'un test, la t�te de lecture de \TeX{} \emph{ne lit pas} tout le code d�pendant du test (jusqu'au \tidx{fi}) pour stocker en m�moire les codes � ex�cuter selon l'issue du test afin de mettre l'un ou l'autre sur la pile juste apr�s avoir effectu� le test. Non, apr�s avoir ex�cut� le test elle continue sa lecture lin�aire, mais elle \emph{sait} qu'elle se trouve dans la port�e d'un test et qu'� un moment ou � un autre, elle aura � lire \tidx{fi}, �ventuellement pr�c�d� d'un \tidx{else}.

Pour que ce point soit clair, mettons-nous � la place de la t�te de lecture de \TeX{} qui doit ex�cuter le test suivant (cas \no1) :

\centrecode-\if<test><arguments><code vrai>\else <code faux>\fi-

\noindent ou (cas \no2) :

\centrecode-\if<test><arguments><code vrai>\fi-

\subsubsection{Test vrai}
Supposons pour l'instant que le test est vrai. Voici l'enchainement des op�rations qui vont avoir lieu :

\begin{enumerate}
       \item tout va commencer par le 1-d�veloppement de �\verb|\if<test><arguments>|� qui va disparaitre � l'occasion de ce d�veloppement;
       \item ce qui est � suivre, le \verb|<code vrai>| est ex�cut� normalement;
       \item le 1-d�veloppement de qui suit est vide. Il s'agit de
       \begin{centrage}\small
               \verb|\else <code faux>\fi|\quad(cas \no1)\kern1cm ou\kern1cm \verb|\fi|\quad(cas \no2)
       \end{centrage}
\end{enumerate}

\subsubsection{Test faux}
Supposons � pr�sent que le test est faux. Voici ce qui va se passer :

\begin{itemize}
       \item cas \no1 :
       \begin{enumerate}
               \item le 1-d�veloppement de �\verb-\if<test><arguments><code vrai>\else-�\linebreak[4] est vide (o� le \tidx{else} est appari� avec le test initial);
       \item ce qui suit, c'est-�-dire \verb|<code faux>| est ex�cut� normalement;
       \item le \tidx{fi} final qui reste est 1-d�velopp� et disparait.
       \end{enumerate}
       \item cas \no 2 : le 1-d�veloppement de �\verb-\if<test><arguments><code vrai>\fi-� est vide et la totalit� de ce code disparait donc en 1-d�veloppement.
\end{itemize}

\begin{regle}
Lorsqu'un test est ex�cut� par une primitive de test \verb|\if<test>|, les primitives \tidx{else} et \tidx{fi} ne sont \emph{pas} supprim�es lorsque le test est fait. Elles restent en place et lorsqu'elles seront rencontr�es plus tard, elles s'autod�truiront par un simple d�veloppement.
\end{regle}

\subsection{Comparer des entiers}
\subsubsection{Le test \texttt{\char`\\ifnum}}
\begin{regle}
La primitive \tidx{ifnum}  effectue une comparaison entre deux entiers. La syntaxe est de la forme

\centrecode-\ifnum<entier1><signe><entier2>
       <code ex�cut� si le test est vrai>
\else
       <code ex�cut� si le test est faux>
\fi-

\noindent o� le \verb-<signe>-, de catcode 12\idx*{catcode!12 (autre)}, est soit �\verb-=-� si l'on veut tester l'�galit� entre les deux entiers, soit �\verb-<-� ou �\verb->-� s'il l'on cherche � tester une in�galit� stricte.
\end{regle}

\showcode/a) \ifnum 15=14 vrai\else faux\fi\qquad% test faux�\tidx*{ifnum}�
b) \ifnum4<200 vrai\else faux\fi\qquad% test vrai
c) \newcount\foo \foo=9
  \ifnum\foo>9 nombre\else chiffre\fi% test faux�\idx*\newcount�/

V�rifions maintenant ce qui a �t� expos� en th�orie sur le 1-d�veloppement d'un test. Pour ce faire, mettons � contribution la macro \verb|\>...<| vue � la partie pr�c�dente :

\showcode/\long\def\>#1<{\detokenize{#1}}�\idx*\long\idx*\detokenize�
\expandafter\>\ifnum5=5 vrai\else faux\fi<\par% test vrai
\expandafter\>\ifnum5=6 vrai\else faux\fi<% test faux
\fi\fi% r�tablir l'�quilibre \ifnum et \fi�\defline\aaa�/

Les trois premi�res lignes de ce code permettent de visualiser les choses, mais rompent l'�quilibre entre les \tidx{ifnum} et les \tidx{fi}. En effet, les \tidx{ifnum} sont ex�cut�s par \verb|\expandafter|, mais les \tidx{fi}, d�tok�nis�s par \verb|\>|, ne seront jamais ex�cut�s par \TeX. Pour r�tablir l'�quilibre et �viter que ce bug ne se propage jusqu'� la fin du code source de ce livre, deux \tidx{fi} ont �t� rajout�s � la ligne \no\aaa.

\begin{exercice}
V�rifier que les appariements des tests avec leur \tidx{else} et \tidx{fi} sont corrects en programmant une macro \verb-\numtest- qui admet un argument de type entier et qui affiche �chiffre� si son argument est compris entre $-9$ et $9$ inclus. Dans les autres cas, la macro doit afficher �nombre positif�  ou �nombre n�gatif�.
\solution
Voici une fa�on  de programmer la macro \verb|\numtest| qui, compte tenu de ce qui a �t� dit sur le d�veloppement des tests, est purement d�veloppable :

\showcode/\def\numtest#1{%
       \ifnum#1>-10 �\tidx*{ifnum}�
               \ifnum#1<10
                       chiffre%
               \else
                       nombre positif%
               \fi
       \else
               nombre n�gatif%
       \fi
}
a) \numtest{3}\qquad
b) \numtest{-67}\qquad
c) \numtest{-8}\qquad
d) \numtest{21}\qquad
e) \edef\foo{\numtest{2014}}\meaning\foo�\idx*\meaning�/
\end{exercice}
\begin{exercice}
�crire une macro \verb-\normalise- qui admet un argument de type entier positif. Si l'entier est compris entre 0 et 999 compris, cette macro devra afficher son argument avec 3 chiffres, quitte � rajouter des 0 inutiles � gauche pour satisfaire cette exigence. Dans les autres cas, aucun affichage ne sera fait.

Par exemple, l'argument �17� donnera un affichage de �017� et �8� sera affich� �008�.
\solution
Il suffit d'imbriquer des tests comme � l'exemple pr�c�dent et afficher 00 ou 0 juste avant l'argument \verb-#1- selon le cas. Ici par contre, la branche \tidx{else} n'est pas n�cessaire :

\showcode/\def\normalise#1{%
       \ifnum#1>-1 % ne faire quelque chose que si #1 est positif ou nul�\tidx*{ifnum}�
               \ifnum#1<100 % si <100
                       0% afficher un 0
                       \ifnum#1<10 % si <10
                               0%afficher un autre 0
                       \fi
               \fi
               \number#1 %afficher le nombre�\idx*\number�
       \fi}% affiche le nombre
a) \normalise{749}\qquad
b) \normalise{0017}\qquad
c) \normalise8\qquad
d) \normalise{1789}\qquad
e) \normalise{-18}\qquad
f) \normalise{0}/

Le \idx\number qui se trouve devant l'entier \verb-#1- a deux fonctions :
\begin{itemize}
       \item celle d'afficher \verb-#1- sans provoquer d'erreur de compilation si \verb-#1- est un compteur;
       \item purger les �ventuels 0 inutiles qui se trouvent � gauche de \verb-#1- si celui-ci est �crit explicitement. Ainsi, �crire \verb-\normalise{0017}- m�ne au r�sultat correct.
\end{itemize}

Il reste � remarquer que la macro \verb|\normalise|, puisque son texte de remplacement n'est constitu� que de tests et de caract�res affichables, est purement d�veloppable.
\end{exercice}

\subsubsection{Le test \texttt{\char`\\ifcase}}\tidx*[|(]{ifcase}%
Pour seconder le test \tidx{ifnum}, \TeX{} met � disposition le test \tidx{ifcase} qui op�re �galement sur des entiers. Ce test fait un peu chambre � part dans le monde des tests, car sa syntaxe �chappe � la syntaxe g�n�rale des tests et c'est pourquoi elle est expliqu�e en d�tail ici.

\tidx*[|(]{or}\begin{regle}
Le test \tidx{ifcase} teste si un entier est successivement �gal � 0, 1, 2, ... selon la syntaxe suivante :

\tidx{or}\centrecode-\ifcase<nombre>
       <code ex�cut�> si <nombre> = 0
\or
       <code ex�cut�> si <nombre> = 1
\or
       <code ex�cut�> si <nombre> = 2
etc...
\else
       <code alternatif>% ex�cut� si aucune �galit� pr�c�dente n'est v�rifi�e
\fi-

Les entiers auxquels le \verb|<nombre>| est compar� commencent n�cessairement � 0, sont cons�cutifs et vont aussi loin qu'il y a de branches \tidx{or}. Il est donc n�cessaire d'�crire autant de \tidx{or} que l'on veut envisager de cas.

La branche \verb|\else<code alternatif>| est facultative.
\end{regle}

Voici comment nous pourrions programmer une macro \verb|\mois{<entier>}| qui affiche en toutes lettres le nom du mois dont le num�ro est pass� en argument. Il est m�me possible de donner le mois en cours comme argument avec la primitive \idx\month, se comportant comme un compteur, qui contient le num�ro du mois en cours :

\showcode/\def\mois#1{%
       \ifcase#1\relax�\tidx*{ifcase}�
           \char`\#\char`\#% afficher "##" si argument = 0
       \or janvier\or f\'evrier\or mars\or avril%�\tidx{or}�
       \or mai\or juin\or juillet\or aout%
       \or septembre\or octobre\or novembre\or d\'ecembre%
       \else
           \char`\#\char`\#% afficher "##" sinon
       \fi
}
a) \mois{-4}\qquad
b) \mois{3}\qquad
c) \mois{11}\qquad
d) \mois{20}\qquad
e) \edef\foo{\mois{\month}}\meaning\foo% mois en cours�\idx*\month�/\tidx*[|)]{ifcase}\tidx*[|)]{or}%

\subsection{Programmer un test : syntaxe}
Les primitives de \TeX{} ne suffisent pas --~et de loin~-- � couvrir tous les tests qu'il est possible de faire. On est donc parfois amen� � programmer des \emph{macros} qui effectuent des tests plus complexes � l'aide notamment d'imbrications de tests primitifs. D�cidons d�s � pr�sent que les noms de ces macros commencent aussi par les lettres �\verb|if|� suivies d'autres lettres not�es \verb|<test>|. C'est un choix \emph{arbitraire} et tout autre choix aurait �galement �t� l�gitime : certains font commencer les \emph{macros} de test par les lettres \emph{majuscules} �\verb|IF|� pour ne pas qu'elles soient confondues avec les \emph{primitive}s qui commencent avec des lettres \emph{minuscules}.

La syntaxe de ces macros, diff�rente de celle des primitives de test, fait davantage consensus. Si \verb|\if<test>| est une macro effectuant un test sur ses \verb|<arguments>| (pris comme argument d'une macro), il est extr�mement courant d'adopter la syntaxe suivante, tr�s facile d'utilisation :

\centrecode-\if<test><arguments>
       {<code ex�cut� si le test est vrai>}
       {<code ex�cut� si le test est faux>}-

Basons-nous sur cette syntaxe pour programmer une macro �\ifletter[|(] qui teste si son argument, que l'on suppose constitu� d'un seul caract�re, not� \verb|<car>|, est une lettre \emph{minuscule}. Par souci de concision, notons \verb|<code vrai>| et \verb|<code faux>| les codes ex�cut�s selon les issues des tests :

\centrecode-\ifletter{<car>}
       {<code vrai>}
       {<code faux>}-

Pour effectuer le test avec \tidx{ifnum}, seule primitive de test que nous connaissons pour l'instant, il va falloir exploiter une fa�on d'�crire un entier qui est \verb|`<car>| o� \verb|<car>| est un caract�re. L'entier que cela repr�sente est le code du caract�re \verb|<car>| (voir page~\pageref{definition.entier}). Nous allons �galement tirer parti du fait que les codes des caract�res de �\verb|a|� � �\verb|z|� sont des entiers cons�cutifs. Par cons�quent, \verb|<car>| est une lettre minuscule si l'entier \verb|`<car>| est compris entre les entiers \verb|`a| et \verb|`z| (bornes comprises).

\subsection{Programmer un test : m�thodes}
Compte tenu du fait qu'il existe plusieurs m�thodes pour programmer la \emph{structure} d'une telle macro, nous allons en envisager plusieurs et elles seront num�rot�es pour pouvoir facilement y faire r�f�rence plus tard.

\subsubsection{M�thode \no1 : intuitive}
Une fa�on intuitive de le faire est de faire lire les trois arguments par la macro :

\begin{enumerate}[label={}]
       \item \verb|#1| : le caract�re \verb|<car>| � tester;
       \item \verb|#2| : le \verb|<code vrai>|, ex�cut� si le test est vrai;
       \item \verb|#3| : le \verb|<code faux>|, ex�cut� si le test est faux.
\end{enumerate}

Ensuite, il suffit d'imbriquer 2 tests comme nous l'avons d�j� fait et selon l'issue de ces tests, �crire � l'int�rieur des branches des tests les arguments \verb-#2- ou \verb-#3- :

\showcode/\def\ifletter#1#2#3{%
       \ifnum`#1<`a% si le caract�re est avant "a"�\tidx*{ifnum}�
               #3% ex�cuter "<code faux>"
       \else% sinon
               \ifnum`#1>`z% si le caract�re est apr�s "z"
                       #3% ex�cuter "<code faux>"
               \else% dans tous les autres cas
                       #2% "#1" est une lettre : ex�cuter "<code vrai>"
               \fi
       \fi}
a) \ifletter{4}{vrai}{faux}\qquad
b) \ifletter{t}{vrai}{faux}\qquad
c) \ifletter{D}{vrai}{faux}/

Il y a une certaine inutilit� dans ce code qui est de lire \verb-#2- et \verb-#3- par la macro \verb|\ifletter| pour les r��crire plus loin dans le code. L'id�al serait de ne lire que l'argument \verb-#1-, de faire le test et selon l'issue, de lire l'un des deux arguments qui suivent (et qui n'ont pas encore �t� lus).

\subsubsection{M�thode \no2 : \texttt{\char`\\firstoftwo} et {\char`\\secondoftwo}}
Les macros �\firstoftwo et �\secondoftwo que nous avons �crites � la page~\pageref{firstoftwo} permettent de s�lectionner un argument parmi deux. C'est d'ailleurs parce qu'elles sont utilis�es � l'issue d'un test qu'elles sont si fr�quemment rencontr�es en programmation. La fa�on na�ve de les placer dans les branches des tests serait d'�crire :

\centrecode*-\def\ifletter#1{%
       \ifnum`#1<`a
               \secondoftwo
       \else
               \ifnum`#1>`z
                       \secondoftwo
               \else
                       \firstoftwo
               \fi
       \fi}-

\noindent Mais agir de cette fa�on provoquerait des r�sultats inattendus et des erreurs de compilation. Il ne faut surtout pas oublier que les \tidx{else} et les \tidx{fi} ne sont pas r�sorb�s lorsque le test est fait, mais restent en place pour �tre d�velopp�s (et �limin�s) plus tard ! Il faut donc faire disparaitre les \tidx{else} et les \tidx{fi} \emph{avant} que �\firstoftwo ou �\secondoftwo n'entrent en jeu et ne les prennent � tort comme leurs arguments ! Pour cela, nous savons qu'il faut les 1-d�velopper. Le cas du premier �\secondoftwo est le plus simple : nous mettrons donc un \idx\expandafter avant lui pour faire disparaitre les 7 derni�res lignes.

Pour le test imbriqu�, c'est un peu plus compliqu�. Mettre un \idx\expandafter devant �\firstoftwo et �\secondoftwo fait disparaitre que le \tidx{else} ou le \tidx{fi} int�rieur. Il restera encore le \tidx{fi} de la derni�re ligne � 1-d�velopper. Nous devons donc cr�er un pont d'\idx\expandafter � deux passes pour 1-d�velopper d'abord le \tidx{else} ou le \tidx{fi} int�rieur puis le \tidx{fi} final.

Voici donc comment coder la macro \verb|\ifletter| :

\showcode/\def\ifletter#1{%�\tidx*{ifnum}�
       \ifnum`#1<`a
               \expandafter\secondoftwo% \expandafter 1-d�veloppe "\else...\fi"��*\secondoftwo�
       \else
               \ifnum`#1>`z
                       \expandafter\expandafter\expandafter% 1-d�veloppe "\else...\fi" puis "\fi"
                       \secondoftwo��*\secondoftwo�
               \else
                       \expandafter\expandafter\expandafter%1-d�veloppe "\fi" puis "\fi"
                       \firstoftwo��*\firstoftwo�
               \fi
       \fi}
a) \ifletter{4}{vrai}{faux}\qquad
b) \ifletter{t}{vrai}{faux}\qquad
c) \ifletter{D}{vrai}{faux}/

La macro \verb|\ifetter| est purement d�veloppable (� condition bien s�r que les instructions contenues dans \verb|<code vrai>| et \verb|<code faux>| le soient).

\subsubsection{M�thode \no3 : \texttt{\char`\\romannumeral}}
La m�thode pr�c�dente produit une macro purement d�veloppable, mais le nombre de d�veloppements � faire pour arriver au \verb|<code vrai>| ou \verb|<code faux>| d�pend du nombre de tests faits et donc, d�pend de l'argument. Ne pas savoir � l'avance combien de d�veloppements sont n�cessaires pour arriver au r�sultat escompt� peut se r�v�ler g�nant dans certains cas particuliers.

\Qu el que soit son argument, faisons en sorte que la macro \verb-\ifletter- se d�veloppe en \verb-<code vrai>- ou  \verb-<code faux>- en deux d�veloppements. L'astuce, nous l'avons d�j� vu, consiste � initier une zone de d�veloppement maximal avec la primitive \idx\romannumeral et stopper ce d�veloppement maximal au bon moment en ajoutant \verb*|0 | ou \idx\z@ (ou tout autre nombre n�gatif). Ce moment est ici le d�but de \verb-<code vrai>- ou  \verb-<code faux>- et donc, pour ins�rer cet ajout, il faut lire les deux derniers arguments de la macro \verb|\ifletter| :

\showcode/\def\ifletter#1#2#3{%
       \romannumeral % <- initie le d�veloppement maximal�\idx*\romannumeral�
       \ifnum`#1<`a
               \expandafter\secondoftwo��*\secondoftwo�
       \else
               \ifnum`#1>`z
                       \expandafter\expandafter\expandafter\secondoftwo��*\secondoftwo�
               \else
                       \expandafter\expandafter\expandafter\firstoftwo��*\firstoftwo�
               \fi
       \fi{0 #2}{0 #3}% <- "0 " stoppe le d�veloppement maximal
}
\long\def\>#1<{\detokenize{#1}}�\idx*\detokenize\idx*\long�
a) \expandafter\expandafter\expandafter\>\ifletter{0}{vrai}{faux}<\qquad
b) \expandafter\expandafter\expandafter\>\ifletter{x}{vrai}{faux}</

\subsubsection{M�thode \no4 : macro auxiliaire}
Pour s'�pargner tous ces \idx\expandafter et si nous n'avons pas besoin d'une macro purement d�veloppable, il est judicieux de s'aider d'une macro auxiliaire --~appelons-la \verb|\donext|~-- que l'on rend \idx\let-�gale � �\firstoftwo ou �\secondoftwo dans les branches des tests. Cette macro sera appel�e � la fin, apr�s �tre sorti des branches des tests :

\showcode/\def\ifletter#1{%�\tidx*{ifnum}�
       \ifnum`#1<`a
               \let\donext=\secondoftwo��*\secondoftwo�
       \else
               \ifnum`#1>`z
                       \let\donext=\secondoftwo��*\secondoftwo�
               \else
                       \let\donext=\firstoftwo��*\firstoftwo�
               \fi
       \fi
       \donext% ex�cuter l'action d�cid�e ci-dessus
}
a) \ifletter{4}{vrai}{faux}\qquad
b) \ifletter{t}{vrai}{faux}\qquad
c) \ifletter{D}{vrai}{faux}/

\subsubsection{M�thode \no5 : \texttt{\char`\\csname} et \texttt{\char`\\endcsname}}
La m�thode de loin la plus �l�gante, mais h�las la plus lente est d'�crire les tests \emph{� l'int�rieur} de la paire \idx\csname\linebreak[1]\verb-...-\linebreak[1]\idx\endcsname. Une fois que les tests seront d�velopp�s, que les branches inutiles auront disparu suite au d�veloppement maximal initi� par \idx\csname, il devra rester entre \idx\csname et \idx\endcsname soit �\texttt{firstoftwo}�, soit �\texttt{secondoftwo}�. La fin du mot �\verb|oftwo|� �tant commune � toutes les issues possibles, il est possible de \emph{factoriser} le code en mettant cette partie de mot � la toute fin, juste avant le \idx\endcsname. Cette m�thode pr�sente l'avantage de donner \verb|<code vrai>| ou \verb|<code faux>| en trois d�veloppements, quel que soit l'argument donn� � \verb|\ifletter| :

\showcode/\def\ifletter#1{%�\idx\csname\tidx{ifnum}�
       \csname
               \ifnum`#1<`a
                       second% <- commenter la fin de ligne pour �viter un
               \else%          espace parasite dans le nom de la macro cr��e
                       \ifnum`#1>`z
                               second%
                       \else
                               first%
                       \fi
               \fi
               oftwo%
       \endcsname
}
a) \ifletter{4}{vrai}{faux}\qquad
b) \ifletter{t}{vrai}{faux}\qquad
c) \ifletter{D}{vrai}{faux}/

\begin{exercice}
Comment faudrait-il modifier ce dernier code pour que \verb|\ifletter| teste si son argument est une lettre de l'alphabet, aussi bien minuscule que majuscule ?
\solution
La primitive \idx\lowercase est utile dans ce cas puisqu'elle change toutes les lettres en lettres minuscules et laisse inchang�es les s�quences de contr�le :

\showcode/\def\ifletter#1{%�\idx*\lowercase\idx*\csname\tidx*{ifnum}�
       \lowercase{\csname
               \ifnum`#1<`a second%
               \else
                       \ifnum`#1>`z second\else first\fi
               \fi
       oftwo\endcsname�\idx*\endcsname�
       }%
}
a) \ifletter{4}{vrai}{faux}\qquad
b) \ifletter{t}{vrai}{faux}\qquad
c) \ifletter{D}{vrai}{faux}/

H�las, la primitive \idx\lowercase n'est \emph{pas} d�veloppable ! Autrement dit, elle n'a pas vocation � �tre \emph{d�velopp�e,} mais \emph{ex�cut�e} c'est-�-dire que le remplacement des lettres par des lettres minuscules n'est pas fait sur la pile de \TeX{} mais plus tard, en interne, lors de l'ex�cution. Le code suivant montre qu'un \idx\edef ne provoque aucun d�veloppement sur cette primitive :

\showcode/\edef\foo{\lowercase{AbCd}}\meaning\foo/

Pour en revenir � la macro \verb|\ifletter|, si nous souhaitons qu'elle reste purement d�veloppable, il faut lui faire ex�cuter deux tests de plus (ce qui suppose autant d'imbrications suppl�mentaires) pour tester la place qu'occupe l'entier \verb|`<car>| par rapport aux entiers \verb|`A| et \verb|`Z| :

\showcode/\def\ifletter#1{%�\idx*\csname�
       \csname
               \ifnum`#1<`A second%
               \else
                       \ifnum`#1<`Z first%�\tidx*{ifnum}�
                       \else
                               \ifnum`#1>`a
                                       \ifnum`#1<`z
                                               first%
                                       \else
                                               second%
                                       \fi
                               \else
                                       second%
                               \fi
                       \fi
               \fi
               oftwo%
       \endcsname
}
a) \ifletter{4}{vrai}{faux}\qquad
b) \ifletter{t}{vrai}{faux}\qquad
c) \ifletter{D}{vrai}{faux}\qquad
d) \edef\foo{\ifletter{x}{vrai}{faux}}\meaning\foo\qquad�\idx*\meaning�
e) \edef\foo{\ifletter{=}{vrai}{faux}}\meaning\foo/

Ici encore, 3 d�veloppements sont n�cessaires pour que \verb|\ifletter{<car>}{<vrai>}{<faux>}| se d�veloppe en \verb|<vrai>| ou \verb|<faux>| comme le montre ce sch�ma o� une fl�che repr�sente un d�veloppement :

\begin{centrage}
\small
\verb|\ifletter{<car>}|%
$\longrightarrow$%
\verb|\csname...\endcsname|%
$\longrightarrow
\vcenter{\hbox{�\firstoftwo}\hbox{ou}\hbox{�\secondoftwo}}
\longrightarrow
\vcenter{\hbox{\verb|<vrai>|}\hbox{ou}\hbox{\verb|<faux>|}}$
\end{centrage}
\end{exercice}

\subsubsection{Retour sur la m�thode \no1}
Bien que la m�thode \no1 (dont le code est rappel� ci-dessous) semble identique aux autres m�thodes, il n'en est rien !

\centrecode*-\def\ifletter#1#2#3{%
       \ifnum`#1<`a
               #3%
       \else
               \ifnum`#1>`z
                       #3%
               \else
                       #2%
               \fi
       \fi}-

Le fait que les arguments \verb|#2| et \verb|#3| soient ins�r�s \emph{dans} les branches du test (alors qu'avec �\firstoftwo et �\secondoftwo, ils restent au dehors pour les autres m�thodes) signifie que ces arguments peuvent agir sur ce qui se trouve apr�s eux dans ces m�mes branches\ldots{} Et �ventuellement tout casser ! Imaginons par exemple que l'argument \verb|#3| soit la macro �\gobtwo et que le premier test soit vrai. Lorsque \verb|#3|, c'est-�-dire la macro �\gobtwo va �tre ex�cut�e, elle va capturer les deux arguments qui la suivent pour les faire disparaitre. Tout va se passer comme si un \tidx{else} et un \tidx{ifnum} �taient retir�s du texte de remplacement. Ces deux primitives n'existant plus, l'�quilibre entre les \tidx{fi} et les primitives de test est rompu et \TeX{}, lorsqu'il rencontrera un \tidx{fi} exc�dentaire, �mettra l'erreur de compilation �\texttt{Extra \char`\\fi}�.

Il est donc particuli�rement important qu'une macro effectuant un test avec la syntaxe

\centrecode-\if<test><arguments>{<code vrai>}{<code faux>}<code qui suit>-

\noindent rejette \emph{au-dehors} des branches des tests les arguments \verb|<code vrai>| et \verb|<code faux>| de telle sorte que le code qu'ils contiennent puisse �ventuellement agir sur le \verb|<code qui suit>|. La m�thode \no1, puisque contrevenant � ce principe, est une m�thode � d�conseiller.�*\ifletter[|)]%

\subsection{Exercices sur les entiers}
\begin{exercice}
Programmer une macro �\ifinside[|(] dont voici la syntaxe :

\begin{centrage}
       \small�\ifinside $n$\verb|[|$a$\verb|,|$b$\verb|]{<code vrai>}{<code faux>}|
\end{centrage}

o� $n$, $a$ et $b$ sont 3 entiers avec $a\leqslant b$. La macro �\ifinside teste si $n$ appartient � l'intervalle ferm� $[a\;\string;\;b]$.
\solution

La premi�re id�e est d'imbriquer des tests sur les in�galit�s. Il faut ex�cuter \verb|<code faux>| si $n<a$ ou si $n>b$, et ex�cuter \verb|<code vrai>| sinon :

\showcode/\def\ifinside#1[#2,#3]{%
       \csname
               \ifnum#1<#2 second% si n<a, <code faux>
               \else
                       \ifnum#1>#3 second% si n>b, <code faux>
                       \else       first%  sinon, <code vrai>
                       \fi
               \fi
       oftwo%
       \endcsname
}
a) \ifinside 3[1,8]{oui}{non}\qquad
b) \ifinside -7[-20,-11]{oui}{non}\qquad
c) \ifinside 9[0,6]{oui}{non}\qquad
d) \ifinside -1[-5,1]{oui}{non}/

Une autre approche serait de consid�rer l'entier

\[(n-a)(n-b)\]

Si cet entier est n�gatif ou nul, $n$ est dans l'intervalle. Autrement dit, �\ifinside doit ex�cuter \verb|<code faux>| lorsque cet entier est strictement positif. En s'aidant de \idx\numexpr, un seul test \tidx{ifnum} devient alors n�cessaire pour d�cider si $n$ est dans l'intervalle ou pas\label{ifinside} :

\showcode/\def\ifinside#1[#2,#3]{%
       \ifnum\numexpr(#1-#2)*(#1-#3)\relax>0
               \expandafter\secondoftwo
       \else
               \expandafter\firstoftwo
       \fi
}
a) \ifinside 3[1,8]{oui}{non}\qquad
b) \ifinside -7[-20,-11]{oui}{non}\qquad
c) \ifinside 9[0,6]{oui}{non}\qquad
d) \ifinside -1[-5,1]{oui}{non}/�*\ifinside[|)]
\end{exercice}

\begin{exercice}
Programmer une macro �\absval\verb-{entier}-, purement d�veloppable et qui se d�veloppe en la valeur absolue de l'entier.
\solution
La premi�re id�e est de tester si l'entier est n�gatif auquel cas, nous prendrons l'oppos� de ce nombre en mettant un signe �\verb+-+� devant :

\showcode/\def\absval#1{%�\idx*\number\tidx*{ifnum}�*\absval�
       \ifnum#1<0 \number-#1
       \else      \number#1
       \fi}
a) \absval{-87}\qquad b) \absval{75}\qquad c) \absval{0}��*\absval�/

Mais la meilleure solution serait de se servir du fait que la primitive \idx\number d�veloppe au maximum tout ce qu'elle trouve jusqu'� trouver un caract�re qui ne peut pas appartenir � un nombre. Nous pouvons donc mettre le test \emph{dans} le nombre �valu� par \idx\number, c'est-�-dire apr�s cette primitive. Le d�veloppement maximal de ce test laissera �\verb+-+� si le nombre est n�gatif et rien sinon :

\showcode/\def\absval#1{\number\ifnum#1<0 -\fi#1 }��*\absval�
a) \absval{-87}\qquad b) \absval{75}\qquad c) \absval{0}��*\absval�/

Un fonctionnalit� int�ressante est d'autoriser des expressions arithm�tiques dans l'argument de �\absval. Pour ce faire, nous pouvons �valuer cet argument avec \idx\numexpr :

\showcode/\def\absval#1{\number\ifnum\numexpr#1\relax<0 -\fi\numexpr#1\relax}�\idx*\numexpr\idx*\relax�*\absval�
a) \absval{-87}\qquad
b) \absval{75}\qquad
c) \absval{0}\qquad
d) \absval{-20+13}\qquad% -7 affich� 7
e) \absval{5-3*(-4)+10-50}% -23 affich� 23��*\absval�/

Le seul inconv�nient est que nous �valuons \emph{deux} fois l'expression arithm�tique \verb|#1| ce qui est redondant et source de ralentissement. Un  programmeur rigoureux d�composerait le travail et �crirait deux macros. La premi�re serait charg�e d'�valuer l'expression arithm�tique et de passer comme argument � la seconde macro le \emph{nombre explicitement �crit} qui a �t� obtenu. Celle-ci serait charg�e de donner la valeur absolue de son argument :

\showcode/\catcode`\@11
\def\absval#1{\exparg\absval@i{\number\numexpr#1\relax}}�\idx*\numexpr\idx*\relax�*\absval�*\exparg�
\def\absval@i#1{\number\ifnum#1<\z@-\fi#1 }�\idx*\number\idx*\z@�
\catcode`\@12
a) \absval{-87}\qquad
b) \absval{75}\qquad
c) \absval{0}\qquad
d) \absval{-20+13}\qquad% r�sultat -7 qui est affich� 7
e) \absval{5-3*(-4)+10-50}% r�sultat -23 qui est affich� 23��*\absval�/
\end{exercice}

\label{intdiv}\begin{exercice}
Nous avions vu au chapitre pr�c�dent la macro �\truncdiv qui appliquait la formule suivante pour calculer la troncature du quotient de $x$ par $y$ en utilisant la division de \idx\numexpr :

\[\frac{x-\frac{y-1}2}y\]

Voici le code de la macro tel que nous l'avions �labor�:

\centrecode|\def\truncdiv#1#2{\numexpr(#1-(#2-1)/2)/#2\relax}|�*\truncdiv

La formule n'�tant valable que pour $x$ et $y$ positifs, cette macro donnait des r�sultats erron�s pour des arguments n�gatifs. Modifier la macro �\truncdiv pour qu'elle donne le bon r�sultat, quels que soient les signes de ses deux arguments.
\solution
D�j�, la formule donn�e est �quivalente �
\[\frac{2x-y+1}{2y}\]
qui sera sans doute un peu plus rapide puisqu'il n'y a qu'une seule division.

Puisqu'elle n'est valable que pour les entiers positifs, nous allons reprendre le code de la macro �\truncdiv donn� dans l'�nonc� en rempla�ant les arguments par leur valeur absolue. Pour que le quotient final tienne compte des signes des arguments, nous allons multiplier le quotient par 1, pr�c�d� du signe du premier argument et du signe du second. De cette fa�on, s'ils sont tous les deux positifs, nous aurons \verb|--1| et la primitive \idx\number sait que ce nombre est 1. Si l'on note $\sigma_x$ le signe de $x$, cela donne

\[\sigma_x\sigma_y1\times\frac{2|x|-|y|+1}{2|y|}\]

Pour cela, reprenons la macro �\absval et cr�ons une macro �\sgn qui se d�veloppe en �\verb|-|� si son argument est strictement n�gatif :

\showcode|\def\sgn#1{\ifnum#1<0 -\fi}��*\sgn�
\def\truncdiv#1#2{%��*\truncdiv�*\absval�*\absval�*\truncdiv�
       \numexpr
               \sgn{#1}\sgn{#2}1*% multiplie le quotient ci-dessous par +1 ou -1��*\sgn�
               (2*\absval{#1}-\absval{#2}+1)/(2*\absval{#2})��*\absval�
       \relax
}
a) \number\truncdiv{-8}3\qquad
b) \number\truncdiv{-8}{-3}\qquad
c) \number\truncdiv8{-3}\qquad
d) \number\truncdiv{0}{-5}��*\truncdiv�|

Une optimisation possible de la formule est d'�crire au d�nominateur $2y$ (qui contient le signe de $y$) et supprimer $\sigma_y$ au d�but. Il est aussi possible de d�placer $\sigma_x$ au d�nominateur :

\[\frac{2|x|-|y|+1}{\sigma_x2y}\]

Si $y$ est une expression arithm�tique, il est plus prudent de mettre \verb|#2| (qui repr�sente $y$) entre parenth�ses au d�nominateur. Cela nous donnerait la macro

\centrecode|\def\truncdiv#1#2{%��*\truncdiv�
       \numexpr(2*\absval{#1}-\absval{#2}+1)/(\sgn{#1}2*(#2))\relax��*\absval�*\sgn�
}|

En l'�tat, elle n'est pas satisfaisante, car si \verb|#1| est une expression arithm�tique, �\sgn\verb|{#1}| va provoquer une erreur puisque rien n'est pr�vu pour �valuer l'argument de �\sgn. De plus, l'argument \verb|#2| est �valu� \emph{deux} fois : une fois par �\absval et une autre dans la parenth�se au d�nominateur.

Il faut mettre un peu d'ordre et d�cider que les deux arguments de �\truncdiv doivent tout d'abord �tre calcul�s par une premi�re macro puis �tre transmis en tant que nombres explicitement �crits � une seconde macro qui fera le calcul. Comme les arguments sont d�j� calcul�s, il ne faut pas que \verb|absval| ne les calcule � nouveau. Abandonnons donc cette version de �\absval pour �crire ��\sgn\verb|{<entier>}<entier>|� ce qui arithm�tiquement, est la valeur absolue de l'\verb|<entier>| :

\showcode|\catcode`\@11
\def\sgn#1{\ifnum#1<\z@-\fi}�\idx*\z@�*\sgn�
\def\truncdiv#1#2{%
       \exptwoargs\truncdiv@i{\number\numexpr#1\relax}{\number\numexpr#2\relax}%��*\truncdiv�*\exptwoargs\idx*\number�*\truncdiv�
}
\def\truncdiv@i#1#2{%��*\truncdiv�
       \numexpr(2*\sgn{#1}#1-\sgn{#2}#2+1)/(\sgn{#1}2*#2)\relax��*\sgn�
}
\catcode`\@12
a) \number\truncdiv{-8}3\qquad
b) \number\truncdiv{-8}{-3}\qquad
c) \number\truncdiv8{-3}\qquad
d) \number\truncdiv{0}{-5}\qquad
e) \number\truncdiv{20+2*3}{4-5*2}% 26/(-6) doit donner -4��*\truncdiv�|
\end{exercice}

\begin{exercice}
\def\siecle#1{%
       \ifnum#1=0 \else
               \uppercase\expandafter{\romannumeral\ifnum#1<0-\fi#1 }%
               \raise1ex \hbox{e\ifnum#1=1 r\fi}
               si�cle \ifnum#1<0 avant J.C.\fi
       \fi
}
�laborer une macro �\siecle\verb|{<nombre>}| qui, selon le nombre contenu dans son argument, adapte l'�criture des si�cles :\medbreak
\begin{tabular}{>{\ttfamily\hfill}m{0.5\linewidth}<{\kern1em \normalfont affiche\kern1em}@{}l}
\string\siecle\{19\}&\siecle{19}\\
\string\siecle\{-3\}&\siecle{-3}\\
\string\siecle\{1\}&\siecle{1}\\
\string\siecle\{0\}&\siecle{0}<vide>
\end{tabular}

Pour sur�lever un texte enferm� dans une boite (ici une \idx\hbox), on aura recours � la primitive \idx\raise et on �crira :

\centrecode-\raise1ex \hbox{<exposant>}-

pour �lever l'\verb|<exposant>| de \verb|1ex|.
\solution
Il s'agit de faire quelque chose sauf si l'argument est nul. Nous pouvons donc �crire

\centrecode-\ifnum#1=0 \else<action � faire>\fi-

\noindent mais le moteur \idx\eTeX{}\idx*{moteur!etex} dispose de la primitive \tidx{unless} qui, plac�e devant un test, �change les branches correspondant aux issues du test : ce qui est entre le test et \tidx{else} est �chang� avec ce qui est entre \tidx{else} et \tidx{fi}. Nous �crirons donc ici :

\centrecode-\unless\ifnum#1=0 <action � faire>\fi-

Pour obtenir des chiffres romains en majuscule, nous allons utiliser la primitive \idx\uppercase en ayant pris soin de d�velopper au pr�alable son argument traduit en chiffres romains par \idx\romannumeral. Pour �tre surs que le nombre �valu� est toujours positif, nous �crirons \idx\romannumeral�\absval\verb|{#1}|.

Pour l'� exposant �, nous allons donc utiliser la primitive \idx\raise qui a la facult� d'�lever --~ici d'\verb|1ex|~-- la boite horizontale qui la suit. Cette boite contiendra �\verb|e|� suivi, si la valeur absolue de l'argument est 1, d'un �\verb|r|�. Il faudra ensuite ins�rer �av. J.-C.� si l'argument \verb|#1| est strictement n�gatif. Le code est finalement assez facilement lisible :

\showcode/\def\siecle#1{%��*\siecle�
       \unless\ifnum#1=0 % ne faire quelque chose que si #1 diff�rent de 0�\tidx*{unless}�
               \uppercase\expandafter{\romannumeral\absval{#1}}% chiffres romains majuscules�\defline\aaa\idx*\uppercase\idx*\romannumeral�*\absval�
               \raise 1ex \hbox{e\ifnum\absval{#1}=1 r\fi} si�cle% affiche l'exposant puis "si�cle"
               \ifnum#1<0 {} av. J.-C.\fi% affiche si besoin "av. J.-C."�\idx*\raise\idx*\hbox�*\absval\tidx*{ifnum}�
       \fi
}
a) \siecle{19}\qquad
b) \siecle{-3}\qquad
c) \siecle{1}\qquad
d) \siecle{0}\qquad
e) \siecle{-1}��*\siecle�/

Le \idx\expandafter de la ligne \no\aaa{} est automatiquement d�velopp� puisque \idx\uppercase fait partie de ces macros qui doivent �tre suivie d'une accolade ouvrante et qui donc, d�veloppe au maximum ce qui est entre elle et cette accolade. Le d�veloppement de cet \idx\expandafter provoque celui de \idx\romannumeral qui convertit le nombre en chiffres romains avant que \idx\uppercase ne joue son r�le et �crive les chiffres romains en majuscule.
\end{exercice}

\begin{exercice}
Programmer une macro �\hdif[|(]\verb|{h:m:s}{h':m':s'}| qui calcule le temps qui s'est �coul� entre l'heure \verb|h:m:s| et l'heure \verb|h':m':s'| qui lui est ant�rieure. L'affichage se fera en heures, minutes et secondes :\medbreak

\begin{tabular}{>{\ttfamily\hfill}m{0.6\linewidth}<{\kern1em \normalfont affiche\kern1em}@{}l}
\verb|\hdif{18:51:20}{9:20:10}|&\hdif{10:51:20}{9:20:10}\\
\verb|\hdif{14:20:0}{13:50:0}|&\hdif{14:20:0}{13:50:0}\\
\verb|\hdif{7:50:20}{5:50:20}|&\hdif{7:50:20}{5:50:20}\\
\verb|\hdif{7:50:10}{6:50:20}|&\hdif{7:50:10}{6:50:20}\\
\verb|\hdif{20:00:00}{19:59:15}|&\hdif{20:00:00}{19:59:15}\\
\verb|\hdif{17:13:15}{14:12:45}|&\hdif{17:13:15}{14:12:45}
\end{tabular}
\solution
La soustraction de dur�es exprim�es en heures, minutes et secondes se fait comme au coll�ge :
\begin{enumerate}
       \item effectuer les soustractions ind�pendamment entre les heures, les minutes et les secondes ;
       \item si le nombre de secondes est strictement n�gatif, l'augmenter de 60 et soustraire 1 au nombre de minutes ;
       \item puis, si le nombre de minutes est strictement n�gatif, l'augmenter de 60 et soustraire 1 au nombre d'heures ;
\end{enumerate}

L'algorithme s'annonce finalement assez simple.

Comme pour nous en France, le caract�re �\verb|:|� est parfois rendu actif\footnote{Afin qu'il ins�re une espace ins�cable du type \texttt{\string\kern\codeelement{dimension}} juste avant  �\texttt{\string\string\string\:}�.}, il faut ouvrir un groupe semi-simple et changer son code de cat�gorie \emph{avant} de lire l'argument de \verb|\hdif|. Le groupe semi-simple sera ferm� � la fin, apr�s l'affichage.

La principale m�thode de programmation ici consiste � passer les arguments � une macro � arguments d�limit�s \verb|\hdiff@ii| qui isolera les heures, minutes et secondes, effectuera les soustractions entre nombres exprim�s dans la m�me unit� et ajustera les r�sultats s'ils sont n�gatifs. Pour ce qui est de l'affichage du r�sultat, les nombres d'heures, minutes et secondes ne seront affich�s que s'ils ne sont pas nuls. Enfin, du c�t� de la typographie, une macro temporaire \verb|\inter@space|, vide au d�but, sera rendue \idx\let-�gale � un espace d�s qu'un nombre (d'heures ou de minutes) sera affich�. Elle sera ins�r�e avant le nombre suivant et ainsi cr�era une espace avant minutes ou avant les secondes si celles-ci ont �t� pr�c�d�es par l'affichage d'un nombre.

Voici le code comment� :

\showcode|\catcode`\@11
\edef\saved@catcode{\number\catcode`\:}% sauvegarde du catcode de ":"
\catcode`\:12 % ":" est d�sormais un caract�re non actif normal
\def\hdif{%
       \begingroup% ouvrir un groupe semi-simple�\idx*\begingroup�
               \catcode`\:12 % modifier le catcode de ":"
               \hdif@i% aller lire les deux arguments
}

\def\hdif@i#1#2{% lit les 2 arguments
               \hdif@ii#1-#2\@nil% et les transmet � la macro � argument d�limit�s
}

\def\hdif@ii#1:#2:#3-#4:#5:#6\@nil{%
               %%%%%% calcul des nombres � afficher %%%%%%
               \edef\nb@hrs{\number\numexpr#1-#4\relax}% diff�rence des heures�\idx*\number\idx*\numexpr�
               \edef\nb@min{\number\numexpr#2-#5\relax}% diff�rence des minutes
               \edef\nb@sec{\number\numexpr#3-#6\relax}% diff�rence des secondes
               \ifnum\nb@sec<\z@ % si la diff�rence des secondes est <0�\tidx*{ifnum}\idx*\z@�
                       \edef\nb@sec{\number\numexpr\nb@sec+60\relax}% ajouter 60 sec
                       \edef\nb@min{\number\numexpr\nb@min-1\relax}% enlever 1 aux minutes
               \fi
               \ifnum\nb@min<\z@ % si les minutes sont <0
                       \edef\nb@min{\number\numexpr\nb@min+60\relax}% ajouter 60 min
                       \edef\nb@hrs{\number\numexpr\nb@hrs-1\relax}% enlever 1 aux heures
               \fi
               %%%%%% affichage du r�sultat %%%%%%
               \let\inter@space\empty% pas d'espace avant un nombre pour l'instant
               \ifnum\nb@hrs>\z@ % si les heures sont >0
                       \nb@hrs h% afficher les heures et "h"
                       \let\inter@space\space% espace pour plus tard
               \fi
               \ifnum\nb@min>\z@ % si les minutes sont >0
                       \inter@space% afficher une espace �ventuelle
                       \nb@min min% afficher les minutes et "min"
                       \let\inter@space\space�\idx*\space�
               \fi
               \ifnum\nb@sec>\z@ % si les secondes sont >0�\idx*\z@�
                       \inter@space% afficher une espace �ventuelle
                       \nb@sec s% afficher les secondes et "s"
               \fi
       \endgroup% fermer le groupe ouvert au d�but�\idx*\endgroup�
}
\catcode`\:=\saved@catcode\relax% restaure le code de cat�gorie de ":"
\catcode`\@12
a) \hdif{10:51:20}{9:20:10}\par
b) \hdif{14:20:0}{13:50:0}\par
c) \hdif{7:50:20}{5:50:20}\par
d) \hdif{7:50:10}{6:50:20}\par
e) \hdif{20:00:00}{19:59:15}\par
f) \hdif{17:13:15}{14:12:45}|
\end{exercice}\idx*[|)]{nombre}�*\hdif[|)]\tidx*[|)]{ifnum}%

\chapter{Une premi�re r�cursivit�}\idx*[|(]{r�cursivit�}
Le moment est venu de se jeter dans le grand bain de la r�cursivit� ! En effet, nous en savons assez pour sortir de la programmation lin�aire et passer au stade suivant.

La d�finition la plus commun�ment admise, m�me si elle est un peu laconique tient en ces mots : un algorithme est r�cursif\idx*{r�cursivit�} s'il s'appelle lui-m�me. Dans le cas d'une macro, cela signifie qu'une macro est r�cursive si elle s'appelle elle-m�me, que ce soit directement ou par le truchement d'autres macros interm�diaires. On comprend bien que cela implique qu'une \emph{boucle} se met en place, c'est-�-dire qu'une portion de code sera lue plusieurs fois.

Pour prendre une analogie, nous mettrions en place une \idx{r�cursivit�} si, pour parcourir un trajet rectiligne de A vers B, nous nous fixions comme r�gle de reculer de 10 m�tres � chaque fois que nous passons sur un point pr�cis C du parcours. Le simple bon sens montre que nous n'arriverons jamais � la fin du parcours. En effet, nous serions prisonniers d'une \idx{boucle infinie}, condamn�s � parcourir �ternellement la m�me portion de 10 m�tres ! Pour �viter cet �cueil, il faudrait une r�gle suppl�mentaire, appel�e �\idx{point d'arr�t}� qui permet de sortir de cette boucle. Par exemple

\begin{itemize}
       \item ne rebrousser chemin si le nombre de fois que l'on a vu le point C est inf�rieur � 20;
       \item au point C, continuer sans rebrousser chemin si l'on march� plus d'une heure;
       \item ne rebrousser chemin au point C que si l'on a parcouru moins de \numprint[km]{1}.
\end{itemize}

Il en va de m�me en informatique. Une r�cursivit� \emph{doit} comporter un \idx{point d'arr�t} sans quoi elle devient une \idx{boucle infinie}. Un point \idx{point d'arr�t} est un test sur un param�tre qui �volue avec les it�rations de telle sorte qu'� un moment, ce test change d'�tat et valide la sortie de boucle.
\grandsaut

Ne nous lan�ons pas dans une macro de grande ampleur et dans un premier temps, restons tout de m�me modestes. Fixons-nous comme objectif de programmer une commande �\ncar[|(] qui admet 2 arguments, le premier est un nombre positif $n$ et le second un caract�re. Le but de cette macro sera d'afficher le caract�re $n$ fois.

Cette macro, effectuant un travail tr�s simple, sera un pr�texte pour envisager plusieurs m�thodes de programmation.

\subsubsection{Une premi�re approche}
Il suffit d'un peu de r�flexion pour b�tir un algorithme effectuant l'action voulue. L'approche la plus naturelle fait appel � une variable qui, dans le monde de \TeX{} sera un compteur :

\begin{algo}
       \item assigner 0 au \idx{compteur};
       \item si le compteur est strictement inf�rieur � $n$
       \begin{algo}
       \item afficher le caract�re;
       \item incr�menter le compteur de 1;
       \item retourner en 2;
       \end{algo}
       \item fin de l'algorithme
\end{algo}

Comment s'y prendre pour coder un tel algorithme en \TeX{}? Tout d'abord, nous voyons que le code correspondant au point 2 est parcouru plusieurs fois avec des valeurs diff�rentes du compteur. Cette portion de code sera donc n�cessairement \emph{r�cursive}. Par cons�quent, le point 1 sera d�volu � une macro qui initialisera le compteur � 0 et passera la main � une deuxi�me macro, amen�e � s'appeler elle-m�me. Une macro qui proc�de � des initialisations et passe la main � la \emph{vraie} macro principale s'appelle une macro �chapeau�\idx*{macro chapeau}. D�cidons de nommer la macro chapeau \verb|\ncar| et la macro r�cursive \verb|\ncar@i|. Voici l'algorithme pr�c�dent pr�sent� sous une forme d'un \emph{\idx{pseudocode}}, plus proche de la syntaxe avec laquelle on r�dige un programme sans toutefois s'encombrer des subtilit�s syntaxiques :

\begingroup
\numalgofalse
\def\algoleftskip{.1\hsize}
\def\algorightskip{.1\hsize}\label{algo1}
\algorithm[\#]{Afficher $n$ fois un caract�re}/
macro ~ncar~#1#2
       ii:=0% initialise le compteur � 0
       val@max:=#1% stocke la valeur maximale
       car@save:=#2% stocke le caract�re � afficher
       ~ncar@i~% appeler la macro r�cursive
~fin~\medskip
macro ~ncar@i~
       ~si~ ii < val@max% si la valeur maxi n'est pas atteinte
               afficher car@save
               ii:=ii + 1% incr�menter le compteur
               ncar@i% recommencer
       ~finsi~
~fin~/
\endgroup

Il est utile de remarquer que la boucle mise en place dans la macro \verb|ncar@i| est de type � tant que�. En effet, dans un pseudocode adapt� � un langage de plus haut niveau que ne l'est \TeX\footnote{Le format \LaTeX{} fournit une macro \texttt{\string\@whilenum} qui est un � tant que � o� le test fait est une comparaison sur des entiers.}, on aurait pu �crire :

\begingroup
\numalgofalse
\def\algoleftskip{.1\hsize}
\def\algorightskip{.1\hsize}
\algorithm[\#]{Macro ncar@i}/
macro ~ncar@i~
       ~tant que~ ii < val@max% tant que la valeur maxi n'est pas atteinte
               afficher car@save
               ii:=ii + 1% incr�menter le compteur
       ~fin tant que~
~fin~/
\endgroup

Il suffit maintenant de traduire en \TeX{} le premier \idx{pseudocode}, plus proche du niveau de \TeX{} que ne l'est le second :

\showcode/\newcount\ii�\idx*\newcount�
\catcode`\@=11
\def\ncar#1#2{%
   \ii=0 % initialise le compteur � 0
   \def\val@max{#1}% stocke la valeur maximale
   \def\car@save{#2}% stocke le caract�re � afficher
   \ncar@i% appelle la macro r�cursive
}
\def\ncar@i{%�\tidx*{ifnum}�
 \ifnum\ii<\val@max% si la valeur maxi n'est pas atteinte
   \car@save% afficher le caract�re
   \advance\ii 1 % incr�menter le compteur�\idx*\advance�
   \ncar@i% recommencer�\defline\aaa�
 \fi
}
\catcode`\@=12
\ncar{7}{*}\par
\ncar{13}W\par
\ncar{10}{foobar }/\idx*[|)]{compteur}

Cela fonctionne comme attendu, et m�me au-del� puisque le code � reproduire est stock� dans une macro et donc, ce code peut �tre constitu� de plusieurs caract�res et pourrait aussi bien contenir des s�quences de contr�le. Ce code comporte n�anmoins un d�faut : la r�cursivit� mise en place n'est pas terminale!

\begin{regle}
Une \idx[!terminale]{r�cursivit�} est terminale lorsque rien n'est laiss� sur la pile lors de l'appel r�cursif.

Pratiquement, la r�cursivit� est terminale si l'appel r�cursif intervient \emph{en dernier} dans le code de la macro qui s'appelle elle-m�me ou intervient apr�s avoir supprim� par d�veloppement tout ce qui se trouve apr�s cet appel.
\end{regle}

Ici ce n'est pas le cas puisque lorsque la macro \verb-\ncar@i- s'appelle elle m�me � la ligne \no\aaa{}, il reste encore le \tidx{fi} avant la fin du code de la macro. Ce \tidx{fi}, r�sidu non encore r�sorb� du test \tidx{ifnum}, va rester sur la pile pour �tre lu plus tard. Par cons�quent, dans les exemples ci-dessus, il y aura 7, 13 ou 10 \tidx{fi} qui vont s'accumuler sur la pile pour qu'apr�s le dernier test (qui sera n�gatif), ils soient tous lus ce qui provoquera leur disparition par d�veloppement. Pour ne pas surcharger inutilement la pile de \TeX{}, il faut supprimer le \tidx{fi} \emph{avant} d'effectuer l'appel r�cursif. Il suffit ici de placer un \idx\expandafter avant l'appel r�cursif \verb-\ncar@i- pour 1-d�velopper le \tidx{fi}.

Mais il y a plus grave\ldots{} En plus de la r�cursivit� non terminale\idx*{r�cursivit�!terminale}, le code donn� ci-dessus comporte une faute de programmation. Comme nous l'avons vu, lorsque \TeX{} lit le nombre qui suit le signe de comparaison \verb-<-, il d�veloppe au maximum\idx*{d�veloppement maximal} tout ce qu'il trouve jusqu'� trouver quelque chose qui ne peut entrer dans la composition d'un nombre. Il va donc d�velopper \verb-\val@max- (dont le d�veloppement est constitu� de chiffres) et va poursuivre en d�veloppant \emph{aussi} \verb-\car@save-. Si jamais le d�veloppement de \verb-\car@save- est un chiffre ou commence par un ou plusieurs chiffres, ceux-ci vont entrer dans la composition du nombre et, �tant absorb�s lors de cette lecture, ils ne seront plus disponibles pour l'affichage. Non seulement le test se fera sur une valeur fausse, mais un ou plusieurs caract�res pr�vus pour �tre affich�s seront captur�s par le test et rendus indisponibles pour l'affichage.

Nous pouvons en faire l'exp�rience avec ce code :

\showcode/\newcount\ii�\idx*\newcount�
\catcode`\@=11
\def\ncar#1#2{%
   \ii=0 % initialise le compteur � 0
   \def\val@max{#1}% stocke la valeur maximale
   \def\car@save{#2}% stocke le caract�re � afficher
   \ncar@i% appelle la macro r�cursive
}
\def\ncar@i{%
 \ifnum\ii<\val@max% si la valeur maxi n'est pas atteinte
   \car@save% afficher le caract�re
   \advance\ii 1 % incr�menter le compteur�\idx*\advance�
   \ncar@i% recommencer
 \fi
}
\catcode`\@=12
\ncar{2}{3a}/

Ici, le premier test qui est fait, alors que \verb|\ii| vaut 0, est :

\centrecode-\ifnum\ii<23-

\noindent o� le 2 est le d�veloppement de \verb|\val@max| et le 3 est le d�but de celui de \verb|\car@save|. Ce test est vrai et le restera jusqu'� ce que le compteur vaille 23. La macro \verb|\ncar@i| va donc s'appeler 23 fois, et le �\verb|a|�, qui stoppe la lecture du nombre, sera donc affich� 23 fois.

Pour �viter que \TeX{} ne d�veloppe trop loin, il \emph{faut} mettre un \idx\relax\footnote{On pourrait aussi mettre une macro qui se d�veloppe en un espace puisqu'un espace stoppe la lecture du nombre et, contrairement � \idx\relax, est absorb� par cette lecture. On peut donc remplacer \idx\relax par \texttt{\string\space}.} apr�s \verb-\val@max- pour stopper la lecture du nombre. La bonne fa�on de coder la macro \verb-\ncar@i- est donc :

\centrecode-\def\ncar@i{%
 \ifnum\ii<\val@max\relax
   \car@save
   \advance\ii 1
   \expandafter\ncar@i
 \fi}-
\grandsaut

Voici maintenant deux autres variantes pour coder cette macro :

\begin{enumerate}
       \item on peut utiliser une macro auxiliaire \verb-\donext- qui sera �gale, selon l'issue du test, aux instructions � effectuer s'il est positif et � \idx\relax sinon. La macro sera appel�e apr�s �tre sorti des branches du test :

\centrecode-\def\ncar@i{%
       \ifnum\ii<\val@max\relax
               \def\donext{\car@save \advance\ii 1 \ncar@i}%
       \else
               \let\donext\relax
       \fi
       \donext
}-
       \item une autre m�thode, plus �l�gante et plus �conome, car elle se passe d'une macro temporaire consisterait, selon l'issue du test, � lire l'argument entre accolades se trouvant juste apr�s le \tidx{fi} ou � manger cet argument. Pour ces deux actions, on utilise les macros d�j� d�finies �\identity et �\gobone (voir page~\pageref{identity}) :

\centrecode-\def\ncar@i{%
       \ifnum\ii<\val@max\relax
               \expandafter\identity% ex�cute...��*\identity�
       \else
               \expandafter\gobone% ou mange...
       \fi
       {\car@save \advance\ii 1 \ncar@i}%... ce code
}-
\end{enumerate}

\begin{exercice}
Trouver un moyen pour programmer la macro \verb-\ncar{n}{<car>}- sans programmer aucune boucle ni aucune r�cursivit�.

L'exercice est vraiment difficile et tient davantage lieu de curiosit� ou d'acrobatie \TeX nique que de vraie m�thode.
\solution
Nous allons mettre � contribution la primitive \idx\romannumeral et utiliser une de ses propri�t�s : si un nombre est sup�rieur � 1000, alors cette macro produit un nombre en chiffres romains qui commence avec autant de fois le caract�re �\verb|m|� (de catcode 12\idx*{catcode!12 (autre)}) qu'il y a de milliers dans le nombre pass� en argument :

\showcode/a) \romannumeral 9600 \qquad b) \romannumeral 12000/

Lorsque nous allons appeler la macro \verb-\ncar{#1}{#2}- il va suffire d'ajouter �000� apr�s le nombre \verb-#1- pour obtenir \verb-#1- fois le caract�re �\verb|m|� via la primitive \idx\romannumeral. Il ne nous restera plus qu'� � transformer � le caract�re �\verb|m|� vers le caract�re que nous souhaitons afficher. Nous avons d�j� vu comment le faire � l'aide de \idx\lccode et la primitive \idx\lowercase :

\showcode/\def\ncar#1#2{%
       \begingroup�\idx*\begingroup\idx*\lccode�
       \lccode`\m=`#2 % dans \lowercase, les "m" deviennent des "#2"
       \lowercase\expandafter{\expandafter\endgroup\romannumeral#1000 }%�\idx*\lowercase\idx*\endgroup\idx*\romannumeral�
}
a) \ncar{7}{*}\qquad
b) \ncar{15}{\%}\qquad
c) \ncar{10}{4}/

Comme toutes les primitives devant �tre suivies d'une accolade ouvrante, \idx\lowercase d�veloppe au maximum\idx*{d�veloppement maximal} tout ce qui se trouve entre elle et cette accolade. Le d�veloppement d'un pont d'\idx[|etc]\expandafter\forbidindex\expandafter{} exploite ici cette propri�t� pour propager le d�veloppement et 1-d�velopper \verb*-\romannumeral#1000 -. Ce d�veloppement est \emph{n�cessaire} car sans lui, l'argument de \idx\lowercase serait :

\centrecode-\endgroup\romannumeral#1000 -

\noindent et comme cet ensemble de tokens ne contient pas le token �\verb|m|�, \idx\lowercase n'aurait aucune action et ce code serait lu tel quel.

Nous r�pondons bien � l'�nonc� de l'exercice, aucune r�cursivit� ou boucle \emph{explicite} n'a �t� utilis�e. Il est �vident qu'en coulisses, \TeX{} utilise une boucle lorsqu'il ex�cute la primitive \idx\romannumeral.
\end{exercice}

\Qu elle que soit la m�thode employ�e pour parvenir � nos fins, aucune d'entre elles n'est \emph{purement d�veloppable}. Si nous �crivions

\centrecode-\edef\foo{\ncar{3}{*}}-

\noindent le texte de remplacement de \verb|\foo| ne serait pas �\verb|***|�.. La raison tient au fait que les textes de remplacements de \verb|\ncar| ou \verb|\ncar@i| contiennent des s�quences de contr�le non d�veloppables :

\begin{itemize}
       \item un compteur \verb|\ii|;
       \item la primitive \idx\def;
       \item la primitive \idx\advance.
\end{itemize}

\subsubsection{Une approche purement d�veloppable}
Pour construire une macro purement d�veloppable, il faut proscrire toutes les primitives non d�veloppables contenues dans le code actuel : \idx\advance, \idx\relax, \idx\def et les appels aux compteurs. La question qui se pose naturellement est : � sans compteur, comment compter � ?

Le r�ponse tient dans la primitive de \idx\eTeX : \idx\numexpr. L'id�e est de programmer \verb-\ncar- pour que cette macro s'appelle elle-m�me en d�cr�mentant son premier argument avec \idx\numexpr; cet argument ira donc \emph{en d�croissant} de la valeur maxi � 0, alors que c'�tait l'inverse pour les versions vues jusqu'alors. Le fait que \verb|\ncar| s'appelle directement elle-m�me rend inutile toute macro auxiliaire. Voici ce que devient l'algorithme, toujours du type � tant que �, qui tend vers une extr�me simplicit� :

\begingroup
\numalgofalse
\def\algoleftskip{.1\hsize}
\def\algorightskip{.1\hsize}
\algorithm[\#,\{,\}]{D�cr�menter le 1\ier{} argument}/macro ~ncar~#1#2
               ~si~ #1 > 0
                       afficher #2
                       appeler ~ncar~{#1-1}{#2}
               ~fin si~
~fin~/
\endgroup

Du c�t� de \TeX{}, l'appel r�cursif prendra la forme suivante :

\centrecode/\exparg\ncar@i{\number\numexpr#1-1}{#2}/

\noindent o� �\exparg 1-d�veloppe \idx\number qui lance \idx\numexpr qui � son tour, effectue le calcul \verb/#1-1/. Tout cela donnera un argument de �5� si \verb-#1- vaut �6�. Regardons le code fonctionner sur un exemple :

\showcode/\def\ncar#1#2{%
 \ifnum#1>0 % <- espace apr�s le "0"
   #2% affiche le caract�re
   \exparg\ncar{\number\numexpr#1-1}{#2}% appel r�cursif�\idx*\number\idx*\numexpr�*\exparg�
 \fi
}
a) \ncar{7}{*}\qquad
b) \ncar{13}{W}\qquad
c) \edef\foo{\ncar{5}{7}}\meaning\foo/

La premi�re chose importante � noter que le 0 est suivi d'un espace ce qui stoppe la lecture du nombre et qui met � l'�cart \verb-#2-, m�me s'il commence par des chiffres. La seconde remarque est que cette r�cursivit� n'est pas terminale\idx*{r�cursivit�!terminale} puisque le \tidx{fi} n'est pas mang� avant l'appel r�cursif. Comme cela a �t� vu pr�c�demment, les macros �\identity et �\gobone r�glent ce probl�me :

\showcode/\def\ncar#1#2{%
       \ifnum#1>0 \expandafter\identity% si #1>0 ex�cuter...��*\identity�
       \else      \expandafter\gobone% ...sinon manger��*\gobone�
       \fi% ce qui est entre ces accolades :
               {#2% afficher le caract�re
               \exparg\ncar{\number\numexpr#1-1}{#2}% appel r�cursif�\idx*\number\idx*\numexpr�*\exparg�
               }%
}
a) \ncar{7}{*}\qquad
b) \ncar{13}{W}\qquad
c) \edef\foo{\ncar{5}X}\meaning\foo/

\subsubsection{Jouer avec le \texttt{\char`\\fi}}
Une autre ruse de \TeX pert consiste � �crire une macro � argument d�limit� qui \emph{inverse} l'ordre d'un \verb-<code>- quelconque et du prochain \tidx{fi}, sous r�serve que le \verb|<code>| ne contienne pas un \tidx{fi} :

\centrecode-\long\def\antefi#1\fi{\fi#1}-�*\antefi

\noindent La macro �\antefi lit tout le code \verb-#1- jusqu'au prochain \tidx{fi} qui sert de d�limiteur. Ce \tidx{fi}, partie int�grante de la macro, n'est pas ex�cut� et n'est donc pas pas pris en compte par le compteur interne de \tidx{fi}. Ce n'est que lorsque �\antefi se d�veloppera que le \tidx{fi}, token rendu en premier, marquera pour \TeX{} la fin de la port�e du test.

\showcode/\long\def\antefi#1\fi{\fi#1}��*\antefi\idx*\long�
\def\ncar#1#2{%
       \ifnum#1>0
               \antefi% comme si le \fi �tait "d�plac�" ici��*\antefi�
               #2% affiche le caract�re
               \exparg\ncar{\number\numexpr#1-1}{#2}% appel r�cursif�\idx*\number\idx*\numexpr�
       \fi
}
a) \ncar{7}{*}\qquad
b) \ncar{13}{W}\qquad
c) \edef\foo{\ncar{5}X}\meaning\foo/

La pr�sence d'un \tidx{else} provoquerait une erreur si le �\antefi se trouvait avant le \tidx{else}. Dans ce cas, le �\antefi se d�velopperait en \tidx{fi} suivi d'un code \verb|#1| contenant un \tidx{else} qui du coup, se retrouverait orphelin, en dehors du territoire du test. En revanche, �\antefi fonctionne bien dans la branche \tidx{else}\linebreak[1]\verb-...-\tidx{fi} d'un test.

\begin{exercice}
Comment peut-on modifier la d�finition de �\antefi pour que l'astuce fonctionne aussi bien avec la pr�sence d'un \tidx{else} que sans ?
\solution
Nous pouvons d�finir comme argument \emph{non d�limit�} le code � mettre apr�s le \tidx{fi}. Appelons �\afterfi cette macro qui aura pour mission de placer apr�s le \tidx{fi} son argument :

\centrecode/\long\def\afterfi#1#2\fi{#2\fi#1}/

\noindent De cette fa�on, si l'argument d�limit� \verb-#2- contient un \tidx{else}, ce \tidx{else} est recopi� tel quel et se trouve devant le \tidx{fi} et donc n'occasionnera aucune erreur de compilation.

\showcode/\long\def\afterfi#1#2\fi{#2\fi#1}��*\afterfi\idx*\long�
\def\ncar#1#2{%
       \ifnum#1>0
               \afterfi{\exparg\ncar{\number\numexpr#1-1}{#2}}% <- argument renvoy� apr�s le \fi�\idx*\number\idx*\numexpr�*\afterfi�
               #2% <- ceci reste avant le \fi
       \fi
}
a) \ncar{7}{*}\qquad
b) \ncar{13}{W}\qquad
c) \edef\foo{\ncar{5}X}\meaning\foo/
\end{exercice}

\subsubsection{Une solution avec \texttt{\char`\\expandafter}}
Si nous �tions �tait \emph{certains} que l'argument \verb|#2| �tait compos� d'un unique token, nous pourrions nous passer de �\antefi ou �\afterfi et sauter ce token pour aller d�velopper le \tidx{fi} et rendre la r�cursivit� terminale\idx*{r�cursivit�!terminale}. Il suffirait de propager le d�veloppement avec des \idx\expandafter :

\centrecode/\def\ncar#1#2{%
 \ifnum#1>0%
   #2%
   \expandafter\ncar\expandafter{\number\numexpr#1-1\expandafter}%
   \expandafter{\expandafter#2\expandafter}%
 \fi
}/

Mais l'appel \verb|\ncar{5}{foobar}| ne serait pas une r�cursivit� terminale\idx*{r�cursivit�!terminale} puisque dans

\centrecode/{\expandafter foobar\expandafter}/

\noindent le pont d'\idx\expandafter est tr�s insuffisant pour sauter tous les tokens de � foobar �. Si nous voulons nous passer de �\antefi, ce qu'il y a de mieux � faire est de mettre l'argument \verb|{#2}| apr�s le \tidx{fi}. Si le test est faux, il faudra manger cet argument avec �\gobone et s'il est vrai, \verb|{#2}| reste en place et devient le 2\ieme{} argument de �\ncar. Pour cela, l'astuce consiste � exploiter le fait que la primitive \idx\numexpr engage un d�veloppement maximal. Il suffit donc de placer un \idx\expandafter � la fin de cette zone pour d�velopper (et donc faire disparaitre) la branche \verb|\else...\fi| :

\showcode/\def\ncar#1#2{%
 \ifnum#1>0
   #2% afficher le caract�re
   \expandafter\ncar\expandafter% le pont d'\expandafter lance \number et \numexpr
               {\number\numexpr#1-1\expandafter}% le dernier \expandafter mange "\else...\fi"�\idx*\number\idx*\numexpr�
 \else
   \expandafter\gobone% si le test est faux, manger {#2} ci-dessous��*\gobone�
 \fi{#2}%
}
a) \ncar{7}{*}\qquad
b) \ncar{13}{W}\qquad
c) \edef\foo{\ncar{5}X}\meaning\foo/

\subsubsection{D�finir une sous-macro}
Examinons une derni�re m�thode pour construire une r�cursivit� terminale\idx*{r�cursivit�!terminale}. � l'int�rieur de la macro \verb-\ncar-, nous allons d�finir une � sous-macro � nomm�e \verb-\ncar@i- qui elle, n'admettra qu'un seul argument, le nombre not� \verb|i| qui compte les it�rations. Gr�ce � l'imbrication des macros, les arguments de la macro m�re \verb-\ncar- seront accessibles dans le texte de remplacement de \idx{macro fille} \verb-\ncar@i-. Rappelons-nous que le token \verb-#- doit �tre doubl� � chaque niveau d'imbrication de \verb|\def| pour distinguer les arguments de la macro m�re de ceux de la macro fille.

Nous compterons dans \emph{l'ordre croissant}, de 0 la valeur maxi.

\showcode/\catcode`\@11
\def\ncar#1#2{%
       \def\ncar@i##1{%
               \ifnum##1<#1 % si i < valeur maxi
               #2% afficher le caract�re
               \exparg\ncar@i{\number\numexpr##1+1\expandafter}% puis recommencer avec i+1�\idx*\number\idx*\numexpr�
               \fi% \fi mang� par le \expandafter en fin de zone de \numexpr
       }%
       \ncar@i{0}% commence avec la valeur "compteur" 0
}
\catcode`\@12
a) \ncar{7}{*}\qquad
b) \ncar{13}{W}\qquad
c) \ncar{5}{X}/

L'inconv�nient de cette m�thode est que la macro \verb-\ncar- n'est pas purement d�veloppable puisque son texte de remplacement contient la primitive \idx\def�\ncar[|)].

\begin{exercice}\label{compte}�*\compte[|(]%
�crire une macro \verb-\compte{<nombre>}- qui affiche les entiers de 1 � \verb-<nombre>-, s�par�s les uns des autres par une virgule et une espace. Si le \verb-<nombre>- est n�gatif ou nul, aucun affichage ne sera produit.

On �crira un code non purement d�veloppable utilisant un compteur et un code purement d�veloppable. Dans tous les cas, la r�cursivit� devra �tre terminale.
\solution
Voici un code qui n'est pas purement d�veloppable. Comme au premier exemple vu avec \verb-\ncar-, nous utilisons un compteur et nous stockons la valeur maximale dans la s�quence de contr�le \verb-\val@max-.

\showcode/\catcode`\@11 \newcount\compte@cnt�\idx*\newcount�
\def\compte#1{%
       \def\val@max{#1}\compte@cnt=0 % effectue les initialisations
       \compte@i% appelle la macro principale
}
\def\compte@i{%
       \ifnum\compte@cnt<\val@max% si compteur < valeur maxi
               \advance\compte@cnt1 % incr�menter le compteur�\idx*\advance�
               \number\compte@cnt, % afficher le nombre, la virgule et l'espace�\idx*\number�
               \expandafter\compte@i %recommencer
       \fi
}
\catcode`\@12
a) \compte{9}\qquad
b) \compte{-4}\qquad
c) \compte{2}/

Le probl�me saute aux yeux et r�v�le une erreur de programmation : la virgule et l'espace sont aussi affich�s apr�s le dernier nombre, ce qui ne devrait pas �tre le cas.

La m�thode la plus imm�diate est de tester � l'int�rieur du test principal si, apr�s incr�mentation, \verb-\compte@cnt- est inf�rieur � \verb-\val@max- et si tel est le cas, afficher �\verb*-, -�. Voici donc le code corrig� :

\showcode/\catcode`\@11 \newcount\compte@cnt�\idx*\newcount�
\def\compte#1{\def\val@max{#1}\compte@cnt=0 \compte@i}
\def\compte@i{%
       \ifnum\compte@cnt<\val@max\relax
               \advance\compte@cnt1 �\idx*\advance�
               \number\compte@cnt
               \ifnum\compte@cnt<\val@max , \fi% afficher ", " si le maxi n'est pas atteint�\defline\aaa�
               \expandafter\compte@i
       \fi
}
\catcode`\@12
a) \compte{9}\qquad
b)\compte{-4}\qquad
c) \compte{2}/

Bien qu'il fonctionne parfaitement, ce code n'est pas satisfaisant parce que le test de la ligne \no\aaa{} est fait � chaque it�ration. Certes, le ralentissement qu'il occasionne � chaque fois est insignifiant, mais il est r�el et il se cumule au fur et � mesure des appels. Un programmeur rigoureux optimiserait ce code.

Essayons de supprimer ce test. Nous allons tout d'abord rajouter un test dans la macro \verb-\compte- pour tester si son argument est strictement positif, seul cas o� quelque chose sera affich�. Ce test ne sera donc fait qu'une fois. Dans le cas o� il est positif, la macro r�cursive \verb|\coompte@i| sera appel�e et elle produira l'affichage en deux �tapes :

\begin{itemize}
       \item la valeur du compteur sera affich�e;
       \item le test d�cidant si la macro s'appelle elle-m�me sera fait et s'il est positif, cela signifie qu'il reste encore des valeurs � afficher. La virgule et l'espace seront donc affich�s avant que le compteur ne soit incr�ment� et l'appel r�cursif ne soit ex�cut�.
\end{itemize}

\showcode/\catcode`\@11 \newcount\compte@cnt�\idx*\newcount�
\def\compte#1{%
 \ifnum#1>0 % ne faire quelque chose que si l'argument est positif
   \def\val@max{#1}\compte@cnt=1 % faire les initialisations
   \expandafter\compte@i% appeller la macro r�crusive
 \fi
}
\def\compte@i{%
 \number\compte@cnt\relax % afficher le nombre
 \ifnum\compte@cnt<\val@max\relax % si valeur maxi n'est pas atteinte
   , % afficher la virgule et l'espace
   \advance\compte@cnt1 % incr�menter le compteur�\idx*\advance�
   \expandafter\compte@i % recommencer
 \fi
}
\catcode`\@12
a) \compte{9}\qquad
b) \compte{-4}\qquad
c) \compte{2}/

Passons maintenant � une solution purement d�veloppable dans laquelle, pour compter les it�rations, nous allons utiliser la primitive \idx\numexpr. Nous allons traduire l'algorithme vu ci-dessus de fa�on � nous passer de compteur. Il suffit de passer � la macro \verb-\compte@i- deux arguments, l'un qui contient la valeur � afficher (et qui compte les it�rations � partir de 1) et l'autre la valeur maximale qui est l'argument \verb-#1- de \verb-\compte-. Comme vu dans un exemple pr�c�dent, nous rendons cette fois-ci la r�cursivit� terminale\idx*{r�cursivit�!terminale} en mettant le code \emph{entier} contenant l'appel r�cursif dans un argument apr�s le \tidx{fi} : cet argument sera lu tel quel avec �\identity si le test est positif et sera mang� avec �\gobone dans le cas contraire.

\showcode/\catcode`\@11
\def\compte#1{%
       \ifnum#1>\z@% ne faire quelque chose que si #1 > 0�\idx*\z@�
               \antefi\compte@i{1}{#1}%��*\antefi�
       \fi
}

\def\compte@i#1#2{%
       #1% afficher le nombre
       \ifnum#1<#2 % si le maxi n'est pas atteint
               \expandafter\identity% ex�cuter...��*\identity�
       \else
               \expandafter\gobone% sinon, manger...��*\gobone�
       \fi% le code entre accolades ci-dessous
               {, % afficher la virgule et l'espace
               \exparg\compte@i{\number\numexpr#1+1}{#2}% appel r�cursif�\idx*\number\idx*\numexpr�*\exparg�
               }%
}
\catcode`\@12
a) \compte{9}\qquad
b) \compte{-4}\qquad
c) \edef\foo{\compte{2}}\meaning\foo/

Une variante plus concise aurait �t� possible en utilisant �\antefi dans la macro auxiliaire :

\showcode/\catcode`\@11
\def\compte#1{%
       \ifnum#1>\z@% ne faire quelque chose que si #1 > 0�\idx*\z@�
               \antefi\compte@i{1}{#1}%��*\antefi�
       \fi
}

\def\compte@i#1#2{%
 #1% afficher le nombre
 \ifnum#1<#2 % si le maxi n'est pas atteint
   \antefi% d�place le \fi ici��*\antefi�
   , % affiche la virgule et l'espace
   \exparg\compte@i{\number\numexpr#1+1}{#2}% appel r�cursif�\idx*\number\idx*\numexpr�*\exparg�
 \fi
}
\catcode`\@12
a) \compte{9}\qquad
b) \compte{-4}\qquad
c) \edef\foo{\compte{2}}\meaning\foo/
�*\compte[|)]\end{exercice}

Il faut tirer une le�on de ce chapitre. La programmation de macros r�cursives purement d�veloppables, disqualifiant de fait tout stockage d'information via un compteur, \idx\def ou \idx\toks, oblige � transmettre ces informations sous forme d'arguments. Il devient donc n�cessaire de fournir � chaque it�ration tous les arguments n�cessaires au fonctionnement de la macro m�me si parfois, des arguments invariables (comme la valeur maximale \verb|#2| ci-dessus) doivent �tre lus � chaque fois.

Rendre une macro r�cursive purement d�veloppable est l'assurance qu'elle va fonctionner comme on l'attend dans tous les cas et � ce titre, tend � devenir le Graal que certains recherchent � tout prix. Il est cependant bon de garder � l'esprit que la facilit� et la s�curit� que l'on gagne d'un c�t� cachent une certaine lourdeur dans les m�canismes mis en jeu dans sa programmation. Les contorsions que l'on doit faire notamment au niveau des arguments pour rendre une macro purement d�veloppable impliquent g�n�ralement une programmation beaucoup plus d�licate que si elle ne n'�tait pas.\idx*[|)]{r�cursivit�}

\chapter{Une boucle � for �}�*\for[|(]
\label{for}Nous savons � pr�sent suffisamment de choses pour programmer une structure de contr�le de type � \verb|for| � o� une � variable � --~une macro en r�alit�~-- va prendre les valeurs enti�res successives entre deux entiers $n_1$ et $n_2$. Fixons-nous par exemple la syntaxe sera la suivante :

\begin{centrage}
       \small\verb|\for\<macro>=|$n_1$\verb| to |$n_2$\verb|\do{<code>|
\end{centrage}

\noindent o� le \verb-<code>- pourra contenir la \verb-\<macro- qui tient lieu de variable et qui prend successivement toutes les valeurs de $n_1$ � $n_2$. Compte tenu de sa syntaxe, il est bien �vident que la macro \verb-\for- doit avoir un texte de param�tre contenant des arguments d�limit�s par �=�, �\verb|to|� et par �\verb-\do-�.

\subsubsection{Une premi�re version}
Voici un premier jet, assez intuitif :

\showcode/\catcode`\@11
\def\for#1=#2to#3\do#4{% #1=\<macro>   #2=n1   #3=n2   #4=<code>
       \def#1{#2}% initialise la \<macro> � l'entier n1�\defline\aaa�
       \def\val@max{#3}% stocke n2
       \def\loop@code{#4}% stocke le <code>
       \for@i#1% appelle la macro r�cursive et passe la \<macro> en argument
}
\def\for@i#1{%
       \unless\ifnum#1>\val@max\relax% tant que la \<macro> est <= n2�\tidx*{unless}�
               \loop@code% effectue le code pr�c�demment sauvegard�
               \edef#1{\number\numexpr#1+1}% incr�menter la \<macro>�\idx*\number\idx*\numexpr�
               \expandafter\for@i\expandafter#1% et recommencer apr�s avoir mang� le \fi
       \fi
}
\catcode`\@=12
\for\ii=1to5\do{Maintenant \string\ii\ vaut : \ii.\endgraf}\medbreak�\idx*\medbreak\idx*\string�
"\for\ii=1to0\do{A}"\medbreak% boucle parcourue 0 fois
"\for\ii=1to1\do{A}"\medbreak% boucle parcourue 1 fois�\idx*\medbreak�
\for\ii = 0 to 10 \do {[\ii]}.�\defline\bbb�/

Remarquons tout d'abord que la s�quence de contr�le \idx\do n'est jamais d�finie et peu importe qu'elle le soit\footnote{Comme nous l'avons vu, elle est bel et bien d�finie dans plain-\TeX{} notamment pour seconder la macro \idx\dospecials.} : elle ne sert que de d�limiteur � l'argument \verb-#3- de la macro \verb-\for-.

� la ligne \no\aaa, l'argument \verb|#2|, qui est l'entier $n_1$, est assign� � \verb-#1- qui est la \verb|\<macro>|. C'est une mauvaise id�e si on laisse des espaces --~toujours utiles pour la lisibilit�~-- comme c'est le cas � l'appel de la ligne \no\bbb. Dans ce cas, lors de la premi�re it�ration, \verb-#1- a comme texte de remplacement �\verb*- 0 -�. Pour se pr�munir de cet inconv�nient, il aurait fallu �crire � la ligne \no\aaa{}

\centrecode-\edef#1{\number\numexpr#2\relax}-

\noindent et ainsi tirer parti du fait que non seulement \idx\numexpr �value l'�ventuelle expression arithm�tique \verb|#1|, mais le fait en \emph{ignorant les espaces}. La m�me m�thode doit �tre utilis�e pour stocker l'entier $n_2$ dans \verb|\val@max|.

Plut�t que de d�finir une macro auxiliaire r�cursive \verb-\for@i- \emph{� l'ext�rieur} de la macro principale comme c'est le cas ici, nous avons tout � gagner � la d�finir � l'int�rieur en tant que � \idx{macro fille}�. De cette fa�on, tous les arguments de la macro chapeau sont accessibles. Nous �conomisons donc la macro \verb-\loop@code-.

Remarquons enfin que la macro \verb-\for- n'�tait pas d�clar�e \idx\long, interdisant donc la primitive \idx\par dans ses arguments. Ceci explique pourquoi il faut utiliser \idx\endgraf (une macro \idx\let-�gale � \idx\par) pour provoquer la fin du paragraphe.

\showcode/\catcode`\@11
\long\def\for#1=#2to#3\do#4{%��*\for\idx*\long�
       \def\for@i{%
               \unless\ifnum#1>\val@max\relax% tant que la \<macro> <= n2�\tidx*{unless}�
                       #4% code � ex�cuter
                       \edef#1{\number\numexpr#1+1}% incr�menter \<macro>�\idx*\number\idx*\numexpr�
                       \expandafter\for@i% et recommencer apr�s avoir mang� le \fi
               \fi
       }%
       \edef#1{\number\numexpr#2\relax}% initialise la variable � n1
       \edef\val@max{\number\numexpr#3\relax}% stocke n2
       \for@i% appelle la sous-macro r�cursive
}
\catcode`\@=12
\for\ii = 1 to 5 \do {Maintenant \string\ii\ vaut : \ii.\par}\medbreak�\idx*\medbreak\idx*\string�
"\for\ii=1to0\do{A}"\medbreak% boucle parcourue 0 fois
"\for\ii=1to1\do{A}"\medbreak% boucle parcourue 1 fois�\idx*\medbreak�
\for\ii = 0 to 10 \do {[\ii]}./

\subsubsection{Mise en place d'un incr�ment}
En l'�tat actuel, la macro \verb-\for- incr�mente sa � variable � de 1 � chaque it�ration. Comment s'y prendre pour que cet incr�ment puisse �tre sp�cifi� par l'utilisateur ce qui constituerait en quelque sorte un argument � optionnel �? Il est naturel de penser � cette syntaxe :

\begin{centrage}
       \small\verb|\for\<macro>=|$n_1$\verb| to |$n_2$ \verb|\do| $i$ \verb|{<code>}|
\end{centrage}

Nous allons modifier la macro \verb-\for- pour que l'incr�ment $i$, qui est un entier sign�, soit pris en compte. Si celui-ci n'est pas sp�cifi�, il sera pris �gal � $1$ si $n_1<n_2$ et � $-1$ sinon. L'exercice est difficile, d'autant que nous ne savons pas encore tester si un argument est vide, il faudra donc trouver une autre m�thode !

Il faut d�j� modifier le texte de param�tre de la macro \verb-\for- pour qu'elle prenne un 4\ieme{} argument apr�s le \verb-\do-, suivi ensuite du 5\ieme{} qui sera le code � ex�cuter � chaque it�ration. Ce serait une erreur que de la d�finir ainsi :

\centrecode-\def\for#1=#2to#3\do#4#5{...}-

\noindent Le probl�me avec cette d�finition est que \TeX{} va toujours lire \emph{deux arguments} apr�s le \verb-\do- ! Et si nous omettons l'argument optionnel, \verb-#4- va devenir le \verb-<code>- et \verb-#5- sera l'argument suivant, non destin� � �tre lu par la macro ! Pour �viter un tel m�lange d'arguments, l'argument optionnel recevant $i$ \emph{doit} �tre d�limit� par l'accolade ouvrante\idx*{argument!d�limit�!par accolade} qui marque le d�but du \verb-<code>-. Nous allons donc �crire :

\centrecode-\def\for#1=#2to#3\do#4#{...}-

\noindent Ce faisant, \verb-#4- sera donc tout ce qui se trouve entre \verb-\do- et la prochaine accolade ouvrante, cet ensemble �tant �ventuellement vide. Mais en proc�dant de cette fa�on, l'argument \verb-{<code>}- ne sera pas encore lu. Il faudra appeler une macro auxiliaire charg�e de lire le code devant �tre ex�cut� � chaque fois.

L'autre probl�me qui surgit est que l'argument \verb-#4- peut �tre vide, ou �gal � +4, -2 ou n'importe quel entier sign�. Comment s'y prendre pour transformer cet argument en un nombre, m�me s'il est vide ? L'astuce consiste � mettre un 0 devant cet argument et �valuer le tout avec \idx\numexpr. Nous aurions donc :

\centrecode-\edef\for@increment{\number\numexpr0#4\relax}-

\noindent Par acquit de conscience, assurons-nous que cette astuce fonctionne. Voici les cas qui peuvent se pr�senter :

\begin{itemize}
       \item si \verb-#4- est vide ou r�duit � des espaces, alors le �0� ajout� sera �valu� par \idx\numexpr et donc, \verb-\for@increment- vaudra 0 ;
       \item si \verb-#4- vaut �5� alors, �05� sera �valu� et nous obtiendrons 5;
       \item si \verb-#4- vaut �+4� alors, �0+4� sera �valu� et nous obtiendrons 4 ;
       \item enfin, si \verb-#4- vaut �-10� alors, �0-10� sera �valu� et vaudra -10.
\end{itemize}

Une fois ceci fait, si \verb-\for@increment- est nul, cela traduit une absence d'argument optionnel ou pire, un incr�ment explicitement donn� �gal � 0 par l'utilisateur joueur ou inconscient! Dans ces cas, il suffit de le red�finir � 1 si $n1<n_2$ (soit si \verb-#2-${}<{}$\verb-#3-) et � $-1$ sinon.

Passons � l'�tape suivante : il faut v�rifier que le signe de l'incr�ment (lorsqu'il est explicitement �crit) est � compatible � avec les valeurs de \verb-#2- et \verb-#3-. En effet, si \verb-#2- vaut 4, \verb-#3- vaut 10 et l'incr�ment vaut $-2$, on comprend bien qu'additionner l'incr�ment $-2$ � 4 est une t�che vaine. On n'arrivera jamais � 10 et, apr�s un \emph{tr�s grand} nombre d'it�rations, on va d�passer la borne inf�rieure $-2^{31}+1$ permise pour un nombre, provoquant � ce moment (ou m�me avant) une erreur de compilation.

Un peu d'analyse montre que l'incr�ment est � incompatible � avec les bornes \verb-#2- et \verb-#3- si les entiers $\#3-\#2$ et \verb-\for@increment- sont de signes contraires, c'est-�-dire lorsque le signe de l'expression arithm�tique suivante est strictement n�gatif :

\centrecode/\for@increment*(#3-#2)/

Voici le code :

\showcode/\catcode`\@11
\def\for#1=#2to#3\do#4#{%
       \edef\for@increment{\number\numexpr0#4}% lit et normalise l'argument optionnel�\defline\aaa�
       \ifnum\for@increment=\z@% s'il est nul,�\idx*\z@�
               \edef\for@increment{% le red�finir :
                       \ifnum\numexpr#3\relax<\numexpr#2\relax�\defline\bbb\idx*\numexpr�
                               -% ajoute un signe - si #3<#2
                       \fi
                       1% devant "1"
               }% \for@increment vaut donc 1 ou -1
       \fi
       \ifnum\numexpr\for@increment*(#3-#2)\relax<\z@% si l'argument est incompatible�\defline\ccc\idx*\z@�
               \expandafter\firstoftwo% ex�cuter le 1er argument qui suit��*\firstoftwo�
       \else
               \expandafter\secondoftwo% sinon le second��*\secondoftwo�
       \fi
               {Incr�ment incompatible !\gobone %\gobone mangera le <code> qui � lire�\defline\ddd�
               }%
               {\edef#1{\number\numexpr#2\relax}% initialise la \<macro>
               \edef\cmp@sgn{\ifnum\for@increment<\z@<\else>\fi}% stocke "<" ou ">" pour plus tard�\idx*\z@�
               \expandafter\for@i\expandafter#1\expandafter% appelle la macro r�cursive
                       {\number\numexpr#3\relax}% et lui lui passe la \<macro> (#1) et n2 (#3)
               }%
}

% #1 = \<macro>   #2 = n2
\long\def\for@i#1#2#3{% l'argument #3 (le <code>) est lu � ce moment-l�\idx*\long�
       \def\for@ii{%
               \unless\ifnum#1\cmp@sgn#2\relax% tant que la \<macro> n'a pas d�pass� n2�\defline\fff\tidx*{unless}�
                       #3% ex�cute le <code>�\defline\eee�
                       \edef#1{\number\numexpr#1+\for@increment}% incr�mente la \<macro>�\idx*\number\idx*\numexpr�
                       \expandafter\for@ii% recommence apr�s avoir mang� le \fi
               \fi
       }%
       \for@ii% appelle la sous-macro r�cursive�\defline\ggg�
}%
\catcode`\@=12
a) \for\ii = -4 to 7 \do{(\ii)}\par
b) \for\jj = 20 to -50\do-10 {(\jj)}\par
c) \for\xx = 8 to 185\do 20 {[\xx]}\par
d) \for\yy = 0 to 10\do -2{(\yy)}\par
e) "\for\ii = 1 to 0 \do1{XX}"\par
f) "\for\ii = 1 to 1 \do{A}"\par% boucle parcourue 1 fois
g) \for\ii=1to4\do{\for\jj=0to2\do{(\ii,\jj)}\par}% imbrication de boucles/

Il est utile de reprendre ce code en d�tail, car il comporte beaucoup d'astuces\ldots{} Laissons pour l'instant le cas g o� le probl�me de l'imbrication de boucles sera r�solu un peu plus loin.

� la ligne \no\aaa{}, si le nombre \verb|\for@increment|, r�sultat de l'�valuation de \verb|0#4| est nul, cela signifie que l'argument optionnel \verb|#4| est absent ou �gal � \verb|0|. Dans ce cas, la macro \verb|\for@increment| est red�finie par un \idx\edef et un signe �\verb|-|� est ajout� si \verb|#3| est inf�rieur � \verb|#2| (ligne \no\bbb) de telle sorte que \verb|\for@increment| contienne \verb|1| ou \verb|-1|.

La ligne \no\ccc{} teste si \verb|\for@increment| est � compatible � avec les valeurs \verb|#2| et \verb|#3|. � l'aide des macros �\firstoftwo et �\secondoftwo, un des 2 arguments qui suit est ex�cut� :

\begin{itemize}
       \item le premier argument se contente d'afficher � Incr�ment incompatible � et appelle la macro �\gobone qui mange le \verb-<code>- qui n'a pas encore �t� lu ce qui termine tout le processus. Bien �videmment, il est possible de ne rien afficher et se contenter de mettre �\gobone dans le deuxi�me argument;
       \item le deuxi�me argument d�finit la s�quence de contr�le \verb-\cmp@sgn- pour que son texte de remplacement soit �\verb-<-� si l'incr�ment est n�gatif et �\verb->-� sinon. Ce signe sera utilis� dans un test plus tard. Il ne reste plus ensuite qu'� appeler la macro auxiliaire \verb-\for@i- en lui passant la \verb|\<macro>| (argument \verb-#1-) et l'entier $n_2$ (argument \verb-#3-) pr�alablement �valu� par \idx\numexpr.
\end{itemize}

La macro \verb|\for@i| lira \emph{trois} arguments, les deux que lui passe la macro \verb-\for- et le \verb-<code>- qui doit �tre ex�cut� � chaque it�ration puisque celui-ci n'a pas �t� lu par la macro chapeau \verb-\for-. Comme la macro \verb-\for@i- est appel�e � �tre r�cursive, il est tr�s peu commode --~et maladroit~-- d'installer une r�cursivit� avec trois arguments � lire � chaque appel. Pour �viter cette lourdeur, la macro \verb-\for@i- ne sert que de macro chapeau pour la vraie macro r�cursive \verb-\for@ii- qui n'admet aucun argument puisque, �tant \emph{dans} la macro \verb-\for@i-, elle peut acc�der � ses arguments.

Le code de la macro \verb-\for@ii- est assez simple, le \verb|<code>| est ex�cuter � la ligne \no\eee{} puis la \verb|\<macro>| est incr�ment�e de la valeur sign�e \verb-\for@increment-. La ligne \no\fff{} n�cessite un petit commentaire : le test \tidx{ifnum} s'attend � lire un nombre et d�veloppe tout au maximum jusqu'� trouver un token qui ne puisse pas constituer un entier : la macro \verb|#1| va �tre d�velopp�e et la lecture du nombre ne va pas s'arr�ter. Le d�veloppement va continuer et la macro \verb-\cmp@sgn- va �tre d�velopp�e � son tour. Comme son texte de remplacement est �\verb|<|� ou �\verb|>|�, la lecture du nombre va �tre stopp�e, mais le but recherch�, c'est-�-dire le d�veloppement de \verb|\cmp@sgn| est effectu�. Enfin, le test est construit avec \tidx{unless} ce qui signifie que ce qui se trouve jusqu'au \tidx{fi} est ex�cut� si le test \emph{contraire} est v�rifi�. Ce test contraire correspond � une in�galit� \emph{large} ($\leqslant$ ou $\geqslant$) ce qui implique qu'une it�ration sera faite lorsque la \verb|\<macro>| est �gale � $n_2$.

\subsubsection{Imbrication de boucles : analyse du probl�me}
Comme le cas g l'a mis en �vidence dans le code pr�c�dent, lorsque deux boucles \verb-\for- sont imbriqu�es le fonctionnement attendu n'est pas obtenu et il semble qu'une seule it�ration de la boucle la plus ext�rieure est faite enti�rement :

\centrecode-\for\ii=1to4\do{\for\jj=0to2\do{(\ii,\jj)}\par}-

\noindent se traduit par �(1,0)(1,1)(1,2)�.

Il faut inventer un rem�de qui permet d'imbriquer autant de boucles \verb-\for- que l'on veut. Mais tout d'abord, il faut analyser le probl�me. Par chance, c'est assez simple ici. Dans un premier temps, \verb-\for@i- est appel�e par \verb-\for- ce qui a pour effet de d�finir la macro \verb-\for@ii- avec le texte de remplacement (auquel nous donnons le num�ro~1) suivant :

\centrecode-\unless\ifnum\ii\cmp@sgn4\relax
 \for\jj=0to2\do{(\ii,\jj)}\par
 \edef\ii{\number\numexpr\ii+\for@increment}%
 \expandafter\for@ii
\fi-

Lorsque la macro \verb|\for@ii| est ex�cut�e � la ligne \no\ggg, elle est d�velopp�e et donc, tout ce code est plac� sur la pile pour y �tre ex�cut�. Lorsque la 2\ieme{} ligne de la pile est ex�cut�e, une nouvelle boucle �\for d�marre:

\centrecode-\for\jj=0to2\do{(\ii,\jj)}-

Comme \verb|\ii| vaut 1, cette boucle va afficher �(1,0)(1,1)(1,2)� mais en coulisse, l'irr�parable s'est d�j� produit ! Ce nouvel appel � �\for a red�fini la macro \verb|\for@ii| avec ce texte de remplacement (appel� \no2) :

\centrecode-\unless\ifnum\jj\cmp@sgn2\relax
 (\ii,\jj)%
 \edef\jj{\number\numexpr\jj+\for@increment}%
 \expandafter\for@ii
\fi-

\Qu e va-t-il se passer quand la boucle interne (dont la variable est \verb|\jj|) sera termin�e et que �(1,0)(1,1)(1,2)� sera affich�? La macro \verb|\jj| vaudra 3 et \TeX{} va continuer � lire le code sur sa pile qui est le texte de remplacement \no1 amput� de ses deux premi�res lignes :

\centrecode-\edef\ii{\number\numexpr\ii+\for@increment}%
 \expandafter\for@ii
\fi-

\noindent Par cons�quent, \verb|\ii| va �tre incr�ment� (et vaudra 2). La macro \verb|\for@ii| (dont le texte de remplacement est le \no2) va �tre appel�e et le test

\centrecode-\unless\ifnum\jj\cmp@sgn2\relax-

\noindent sera faux car \verb|\jj| (qui vaut 3) a d�pass� $n_2$ qui est 2. Par cons�quent, aucun code ni aucune r�cursivit� ne seront ex�cut�s. Ce test faux signe donc la fin de la boucle ext�rieure.

\subsubsection{Imbrication de boucles : r�solution du probl�me}
Tous les probl�mes viennent donc de la red�finition de \verb-\for@ii- par la boucle int�rieure et du fait que cette red�finition survive � la fin de la boucle int�rieure. Certes, ex�cuter chaque boucle dans un groupe r�glerait le probl�me, mais cette solution de facilit� emp�cherait toute globalit� au code qui est ex�cut� � chaque it�ration et donc diminuerait les fonctionnalit�s de la boucle.

Le rem�de serait donc de d�finir une macro \verb-\for@ii- sp�cifique � chaque � variable �. Pour cela, la macro chapeau \verb|\for| va appeler une macro \verb|\for@i| charg�e de d�finir la macro r�cursive \verb|\|\boxtoken{for@ii@\string\<macro>} o� \verb|\<macro>| est le d�veloppement de \verb|\string#1|. Par exemple, si l'on ex�cute

\centrecode-\for\xx=1to5\do{X}-

\noindent la macro \verb|\for| va appeler \verb|\for@i| qui va se charger de d�finir et lancer la macro r�cursive \verb-\-\boxtoken{for@ii@\string\xx}. Plus aucun risque de red�finition n'existe, sauf si l'utilisateur fait preuve d'inconscience et utilise le m�me nom de variable pour deux boucles imbriqu�es.

Du c�t� de la m�thode � utiliser, nous allons faire en sorte que \verb|\for| passe � la macro \verb|\for@i| les arguments suivants :

\begin{enumerate}[label={{\ttfamily\char`\#\arabic*} :}]
       \item la macro r�cursive \verb-\-\boxtoken{for@ii@\string\<macro>};
       \item le signe de comparaison explicitement �crit "\verb|<|" ou "\verb|>|";
       \item l'incr�ment sous forme d'un entier explicitement �crit;
       \item la \verb|\<macro>| qui est l'argument \verb|#1| de \verb|\for|;
       \item l'entier $n_2$ qui est l'argument \verb|#3| de \verb|\for|.
\end{enumerate}

Par exemple, si nous �crivons

\centrecode-\for\xx=1to20\do4{X}-

\noindent la macro \verb|\for@i| doit �tre appel�e ainsi :

\begin{centrage}
       \small\verb-\for@i\-\boxtoken{for@ii@\string\xx}\verb-<{4}\xx{20}-
\end{centrage}

Le fait que les arguments \verb|#2|, \verb|#3| et \verb|#5| soient transmis explicitement sous forme de tokens de catcode 12 �vite de cr�er une macro pour les stocker et nous met donc � l'abri de toute red�finition de cette macro par une boucle imbriqu�e.

Prenons le parti de stocker ces 5 arguments dans une macro \verb|\macro@args| d�finie avec \verb|\edef|. Rappelons-nous que dans le texte de remplacement d'un \verb|\edef|, un \idx\noexpand est n�cessaire pour bloquer le d�veloppement d'une s�quence de contr�le : les arguments \verb|#1| et \verb|#4| sont ici concern�s. Une fois la macro \verb|\macro@args| d�finie, l'appel � \verb|\for@i| se fera donc par

\centrecode|\expandafter\for@i\macro@args|

\showcode/\catcode`\@11
\def\for#1=#2to#3\do#4#{%
       \edef\for@increment{\number\numexpr0#4}% lit et normalise l'argument optionnel
       \ifnum\for@increment=\z@% s'il est nul,�\idx*\z@�
               \edef\for@increment{% le red�finir � -1 (si #3<#2) et 1 sinon
                       \ifnum\numexpr#3-#2\relax<\z@ -1\else 1\fi�\idx*\numexpr\idx*\z@�
               }% \for@increment vaut donc 1 ou -1
       \fi
       \ifnum\numexpr\for@increment*(#3-#2)\relax<\z@
               \expandafter\gobone% si argument optionnel incompatible, manger le {<code>}��*\gobone[|etc]\forbidindex\gobone�
       \else
               \edef#1{\number\numexpr#2}% initialise la \<macro>
               \edef\macro@args{% d�finit et d�veloppe les arguments � passer � \for@i
                       %#1=nom de la macro r�cursive :
                       \expandafter\noexpand\csname for@ii@\string#1\endcsname�\idx*\csname\idx*\endcsname\idx*\string�
                       \ifnum\for@increment<\z@ <\else >\fi% #2=signe de comparaison�\idx*\z@�
                       {\for@increment}% #3=incr�ment
                       \noexpand#1% #4=\<macro>�\idx*\noexpand�
                       {\number\numexpr#3\relax}% #5=entier n2�\idx*\number\idx*\numexpr�
               }%
               \antefi% externalise la ligne ci-dessous de la port�e du test��*\antefi�
               \expandafter\for@i\macro@args% appelle \for@i avec les arguments d�finis ci-dessus
       \fi
}

% #1=nom de la macro r�cursive de type "\for@ii@\<macro>"
% #2=signe de comparaison  % #3=incr�ment
% #4=\<macro>  % #5=entier n2  % #6=<code> � ex�cuter
\long\def\for@i#1#2#3#4#5#6{%�\idx*\long�
       \def#1{% d�finit la sous macro r�cursive
               \unless\ifnum#4#2#5\relax% tant que la \<macro> variable n'a pas d�pass� n2�\tidx*{unless}�
                       \afterfi{% rendre la r�cursivit� terminale��*\afterfi\idx*{r�cursivit�!terminale}�
                               #6% ex�cute le code�\defline\bbb�
                               \edef#4{\number\numexpr#4+#3\relax}% incr�mente la \<macro>
                               #1% recommence
                       }%
               \fi
       }%
       #1% appelle la sous-macro r�cursive�\defline\ccc�
}%
\catcode`\@=12
\for\ii=1to4\do{\for\jj=0to2\do{(\ii,\jj)}\par}\medbreak�\idx*\medbreak�

\for\carA= `\A to `\E \do{\for\carB= `w to `z \do{\char\carA\char\carB}\quad}�\idx*[|etc]\quad\forbidindex\quad�/

\begin{exercice}
En l'�tat, la boucle est parcourue autant de fois que l'imposent les bornes et l'incr�ment. Or, dans certains cas, une condition programm�e par l'utilisateur devient vraie au cours des it�rations et � partir de ce moment, ex�cuter les it�rations suivantes devient ind�sirable. Comment programmer une macro �\exitfor qui, ins�r�e dans le \verb|<code>| � ex�cuter, permette de sortir pr�matur�ment de la boucle ?
\solution
La macro �\exitfor est susceptible de se trouver dans le \verb|<code>| � la ligne \no\bbb. Cette macro doit donc annuler l'appel r�cursif de la ligne \no\ccc. Il y a plusieurs moyens de le faire, le plus simple est de charger �\exitfor de red�finir la macro r�cursive \verb|#1| comme ayant un texte de remplacement vide :

\showcode/\catcode`\@11
\long\def\for@i#1#2#3#4#5#6{%�\idx*\long�
       \def\exitfor{\def#1{}}%��*\exitfor�
       \def#1{% d�finit la sous macro r�cursive
               \unless\ifnum#4#2#5\relax% tant que la variable n'a pas d�pass� l'entier max�\tidx*{unless}�
                       \afterfi{% rendre la r�cursivit� terminale��*\afterfi\idx*{r�cursivit�!terminale}�
                               #6% ex�cute le code�\defline\bbb�
                               \edef#4{\number\numexpr#4+#3\relax}% incr�mente la variable #1�\idx*\number\idx*\numexpr�
                               #1% recommence
                       }%
               \fi
       }%
       #1% appelle la sous-macro r�cursive
}%
\catcode`\@=12
\for\ii= 1 to 9 \do{\string\ii{} vaut \ii.\ifnum\ii=5 \exitfor\fi\par}�\idx*\string�*\exitfor�/

Cela fonctionne correctement car il n'y a aucune boucle \verb|for| imbriqu�e.

Dans le cas de boucles imbriqu�es, la macro �\exitfor va �tre d�finie plusieurs fois (une fois par imbrication). Par cons�quent, la derni�re d�finition, celle de la boucle la plus int�rieure, �crase les autres. On peut donc sortir de la boucle la plus int�rieure, mais plus des boucles de niveau sup�rieur.

Le rem�de le plus simple est de donner comme argument � �\exitfor la \verb|\<macro>| correspondant � la boucle de laquelle on souhaite sortir. Ainsi, �\exitfor\verb|#1| red�finirait la macro \verb-\-\boxtoken{for@ii@\string#1} comme ayant un texte de remplacement vide. Pour �tre complets sur le sujet, nous cr�erons aussi la macro �\ifexitfor de syntaxe

\centrecode-\ifexitfor\<macro>{<code vrai>}{<code faux>}-

\noindent Ainsi, �\ifexitfor\verb|\<macro>| permet de savoir, en dehors de la boucle de variable \verb|\<macro>|, si on en est pr�matur�ment sorti ou pas. D�finir �\ifexitfor fait appel au test \verb|\ifx| et � la macro \idx\empty et devient donc, en anticipant un peu, une bonne transition vers le chapitre suivant qui aborde d'autres tests que propose \TeX.

Le code ci-dessous permet de voir plusieurs fa�ons, plus ou moins rapides, de sortir de 2 boucles imbriqu�es :

\showcode/\def\exitfor#1{% #1=\<macro> correspondant � la boucle de laquelle on veut sortir��*\exitfor�
       \defname{for@ii@\string#1}{}�\idx*\csname\idx*\endcsname\idx*\string�*\defname�
}

\def\ifexitfor#1{% envoie vrai si on est pr�matur�ment sorti de la boucle de \<macro> #1��*\ifexitfor�
       % si la macro r�cursive est �gale � la macro "\empty"
       \expandafter\ifx\csname for@ii@\string#1\endcsname\empty�\idx*\string\idx*\empty�
               \expandafter\firstoftwo% c'est qu'on est sortir pr�matur�ment, renvoyer "vrai"��*\firstoftwo�
       \else
               \expandafter\secondoftwo% sinon, renvoyer "faux"��*\secondoftwo�
       \fi
}

% on ne sort QUE de la boucle int�rieure quand \ii=3 donc
% les boucles sont normalement ex�cut�es pour \ii=4 et \ii=5
a. \for\ii=1 to 5\do1{%
    \for\jj=1 to 3\do1{(\ii,\jj) \ifnum\ii=3 \exitfor\jj\fi}%��*\exitfor�
    \qquad
  }

% on sort de la boucle ext�rieure lorsque \ii=3 donc la boucle
% int�rieure est faite enti�rement m�me lorsque \ii=3
b. \for\ii=1 to 5\do1{%
    \for\jj=1 to 3\do1{(\ii,\jj) \ifnum\ii=3 \exitfor\ii\fi}%��*\exitfor�
    \qquad
  }

% on sort de la boucle int�rieure lorsque \ii=3
% et aussi de la boucle ext�rieure � l'aide de \ifexitfor
c. \for\ii=1 to 5\do1{%
    \for\jj=1 to 3\do1{(\ii,\jj) \ifnum\ii=3 \exitfor\jj\fi}%��*\exitfor�
    \ifexitfor\jj{\exitfor\ii}{}% si on est sorti de \jj, sortir aussi de \ii��*\exitfor�*\ifexitfor�
    \qquad
  }/
\end{exercice}�*\for[|)]{}

\chapter[\Qu elques autres tests]{Quelques autres tests}
Apr�s avoir touch� du doigt la syntaxe g�n�rale des tests et leurs particularit�s concernant la fa�on dont ils se d�veloppent, apr�s avoir examin� plus particuli�rement le test \tidx{ifnum}, nous allons dans ce chapitre d�couvrir quelques autres tests de \TeX{}. Le but n'est pas de les passer tous en revue, mais d'examiner ceux qui sont le plus utiles et les utiliser pour en cr�er d'autres.

\section{Le test \texttt{\textbackslash{}ifx}}\tidx*[|(]{ifx}
\subsection{\Qu e teste \texttt{\char`\\ifx} ?}
Un des tests les plus utilis�s est sans doute le test \tidx{ifx}.

\begin{regle}
Le test \tidx{ifx} compare les significations des deux \emph{tokens} qui le suivent. Il a la syntaxe suivante :

\centrecode-\ifx<token1><token2>
       <code vrai>
\else
       <code faux>
\fi-

Il est vrai si la signification des deux tokens est la m�me. Parmi toutes les possibilit�s qui se pr�sentent selon la nature des deux tokens, les trois cas suivants sont les plus courants :

\begin{enumerate}
       \item si les deux tokens sont des caract�res, alors le test est positif si les caract�res sont identiques, c'est-�-dire si leur \idx{code de caract�re} \emph{et} leur catcode sont �gaux;
       \item si les deux tokens sont des \idx{primitive}s, le test est positif si les primitives sont les m�mes;
       \item si les deux tokens sont des macros ou des caract�res actifs\idx*{caract�re actif}, le test \verb-\ifx- compare leurs textes de remplacement : le test est positif si les textes de remplacement sont identiques, c'est-�-dire constitu�s des m�mes tokens avec les m�mes catcodes. La comparaison tient �galement compte des propri�t�s de ces macros, notamment si elles sont \idx\long ou \idx\outer.

       Deux macros non d�finies sont �gales pour \verb-\ifx-, quels que soient leurs noms.
\end{enumerate}
\end{regle}

Contrairement � \tidx{ifnum}, le test \tidx{ifx} ne d�clenche pas un d�veloppement maximal et donc, les deux tokens sont compar�s tels quels.

Si deux tokens appartiennent � deux cat�gories diff�rentes parmi les trois list�es dans la r�gle ci-dessus, le test sera faux. Par exemple, si une macro \verb-\foo- a le texte de remplacement �\verb|a|�, alors le test \verb-\ifx a\foo- est faux :

\showcode/\def\foo{a}\ifx a\foo vrai\else faux\fi/

En effet, le premier token �\verb|a|� est un caract�re, une sorte de primitive pour \TeX{} alors que le second \verb-\foo- est une macro. Notons que la primitive \idx\meaning donne une bonne id�e de ce qu'est la \emph{signification} d'un token, m�me si elle ne dit rien sur les catcodes des tokens composant le texte de remplacement d'une macro (voir les cas \nos6 et 7 ci-dessous) :

\showcode/1) \meaning9\par% un caract�re de catcode 12�\idx*\meaning\idx*{catcode!12\space(autre)}�
2) \meaning a\par% une lettre
3) \def\foo{a}\meaning\foo\par% une macro
4) \long\def\foo{a}\meaning\foo\par% une macro d�clar�e \long�\idx*\long�
5) \meaning\sdlkfj\par% une macro ind�finie
6) \edef\foo{\string a}\meaning\foo\par%\foo contient un "a" de catcode 12�\idx*\string�
7) \def\foo{a}\meaning\foo\par%\foo contient un "a" de catcode 11/

Pour fixer les id�es, effectuons quelques autres tests qui montrent comment r�agit \verb|\ifx| :

\showcode/a) \ifx abvrai\else faux\fi\quad% a est n'est pas �gal � b
b) \ifx++vrai\else faux\fi\quad% le caract�re "+" est �gal � "+"
c) \ifx\relax\par vrai\else faux\fi\quad% \relax n'est pas la m�me primitive que \par
d) \ifx\par\par vrai\else faux\fi\quad% \par et \par sont les m�mes primitives
e) \ifx\sdfk\qlms vrai\else faux\fi\quad% 2 macros non d�finies sont �gales
f) \def\foo{abcd}\def\bar{abc}% \foo et \bar ont des textes de remplacement diff�rents
  \ifx\foo\bar vrai\else faux\fi\quad
g) \def\foo{abcd}\def\bar{abcd }% \foo et \bar ont des textes de remplacement diff�rents
  \ifx\foo\bar vrai\else faux\fi\quad
h) \def\foo{abcd}\def\bar{abcd}
  \ifx\foo\bar vrai\else faux\fi\quad% \foo et \bar ont les m�mes textes de remplacement
i) \long\def\foo{a}\def\bar{a}�\idx*[|etc]\long\forbidindex\long�
  \ifx\foo\bar vrai\else faux\fi\quad% \foo est \long, \bar ne l'est pas
j) \edef\foo{\string a}% \foo contient un "a" de catcode 12�\idx*{catcode!11\space(lettre)}\idx*{catcode!12\space(autre)}\idx*\string�
  \def\bar{a}% \bar contient un "a" de catcode 11
  \ifx\foo\bar vrai\else faux\fi/

\begin{exercice}
Il a �t� dit que le test \verb-\ifx- �tait sensible aux codes de cat�gorie. �crire une macro�*\cmpmacro

\centrecode-\cmpmacro<\macroA><\macroB>{<code vrai>}{<code faux>}-

\noindent qui comparera les macros contenues dans ses deux premiers arguments sans tenir compte des codes de cat�gorie des tokens qui composent leurs textes de remplacement.
\solution
L'id�e et de d�tok�niser le texte de remplacement des deux macros, d'assigner ces deux textes d�tok�nis�s � des macros auxiliaires et enfin, de comparer ces deux macros avec \verb-\ifx-. Pour ne pas laisser ces deux macros auxiliaires derri�re nous, cr�ons-les dans un groupe semi-simple que nous refermerons apr�s la comparaison. Remarquons � cette occasion que la paire \idx\begingroup et \idx\endgroup peut �tre � imbriqu�e � avec les \verb-\ifx-, \tidx{else} et \tidx{fi} d'un test.

\showcode/\def\cmpmacro#1#2{%��*\cmpmacro�
       \begingroup�\idx*\begingroup�
       \edef\tempa{\detokenize\expandafter{#1}}\edef\tempb{\detokenize\expandafter{#2}}%�\idx*\detokenize�
       \ifx\tempa\tempb% si �galit�
               \endgroup\expandafter\firstoftwo% ferme le groupe et lit 1er argument�\idx*\endgroup�*\firstoftwo�
       \else
               \endgroup\expandafter\secondoftwo% sinon, ferme le groupe et lit le 2e argument��*\secondoftwo�
       \fi
}
a) \edef\foo{\string a}\def\bar{a}�\idx*\string�
  \cmpmacro\foo\bar{vrai}{faux}\qquad
b) \edef\foo{\detokenize{$i^2=-1$\relax}}\def\bar{$i^2=-1$\relax}
  \cmpmacro\foo\bar{vrai}{faux}��*\cmpmacro�/
\end{exercice}

\subsection{Le test \texttt{\char`\\ifx}, la \texttt{\char`\\let}-�galit� et les quarks}
Voici une r�gle particuli�re qu'il est utile de connaitre :

\begin{regle}
Le test \tidx{ifx} ne distingue pas deux tokens \idx\let-�gaux.
\end{regle}

Autrement dit, si un token de type \verb|\<macro>| est rendu �gal au token $x$ avec \idx\let, alors, \verb-\ifx- verra \verb|\<macro>| et $x$ �gaux.

Nous pouvons l'observer ci-dessous o� des tokens, � chaque fois \idx\let-�gaux, rendent tous les tests vrais :

\showcode/a) \let\rien\relax      \ifx\rien\relax vrai\else faux\fi\qquad
b) \let\AA=a            \ifx a\AA vrai\else faux\fi\qquad
c) \let\foo=_\let\bar=_ \ifx\foo\bar vrai\else faux\fi/

Pour exploiter la r�gle pr�c�dente, il est parfois commode de cr�er des macros sp�ciales dont le d�veloppement est elles-m�mes, autrement dit \emph{invariantes} par d�veloppement ! Elles portent le nom de �\idx[|(]{quark}s�. Voici comment nous pourrions d�finir un quark nomm� �\quark :

\centrecode-\def\quark{\quark}-

\noindent Bien �videmment, il ne faut jamais qu'un quark ne soit ex�cut� puisqu'en se d�veloppant, il ne change pas : cette propri�t� m�nerait � une \idx{boucle infinie} dont on ne peut sortir que par interruption manuelle. � vrai dire, les quarks ne sont utiles que pour les comparaisons via \tidx{ifx}. Essayons de comprendre pourquoi en prenant par exemple une macro \verb-\test- d�finie comme suit :

\centrecode-\def\test{\quark}-

\noindent Dans ce cas, le test �\verb|\ifx\test\quark|� est vrai parce que �\quark est un quark. Il serait faux s'il ne l'�tait pas. En effet, \tidx{ifx} compare le texte de replacement de \verb|\test| et celui de �\quark : ce texte de remplacement est bien �\quark dans les deux cas.

Le test est �galement positif si \verb|\test| est d�fini par

\centrecode-\let\test=\quark-

\noindent puisque dans ce cas, deux macros \idx\let-�gales sont compar�es.

\showcode/\def\quark{\quark}% d�finit un quark��*\quark�
1) \def\test{\quark} \ifx\quark\test vrai\else faux\fi
\qquad
2) \let\test=\quark  \ifx\quark\test vrai\else faux\fi��*\quark�/

Le fait que \tidx{ifx} donne un test vrai aussi bien pour une macro d�finie par \idx\def ou par \idx\let se r�v�le bien pratique et constitue une particularit� des quarks.

\begin{regle}[D�finition et propri�t�s]
Un quark est une macro dont le texte de remplacement est constitu� de la macro elle-m�me.

Un quark ne doit \emph{jamais} �tre ex�cut�, car �tant invariant par d�veloppement, son traitement par \TeX{} engendrerait une \idx{boucle infinie}.\medbreak

Si \verb|\<quark>| est un quark et si \verb|\<macro>| est d�finie par

\begin{centrage}
\small\verb|\def\<macro>{\<quark>}|\quad {\normalsize ou par}\quad\verb|\let\<macro> = \<quark>|
\end{centrage}

\noindent alors, le test \verb|\ifx\<macro>\<quark>| sera vrai dans les deux cas.
\end{regle}\idx*[|)]{quark}

\section{Applications du test \texttt{\textbackslash ifx}}
\subsection{Tester si un argument est vide}\idx*[|(]{argument!vide}
Il arrive souvent qu'il faille tester si un argument est vide (c'est-�-dire constitu� de 0 token). La m�thode na�ve, mais aussi la plus efficace est la suivante : on assigne avec \verb|\def| cet argument � une \verb|\<macro>| temporaire. Ensuite, on compare avec \verb-\ifx- cette \verb|\<macro>| et la macro nomm�e \idx\empty, d�finie dans plain-\TeX{}\footnote{La macro �quivalente \texttt{\string\@empty} est d�finie dans le format \LaTeX.}, dont le texte de remplacement est vide:�*\ifempty[|(]

\centrecode-\def\empty{}-

Cela donne le code suivant :

\showcode/\def\ifempty#1{%��*\ifempty�
       \def\tempa{#1}% stocke l'argument #1 dans \tempa�\defline\aaa�
       \ifx\tempa\empty% si \tempa = \empty
               \expandafter\firstoftwo% 1er argument��*\firstoftwo�
       \else
               \expandafter\secondoftwo% sinon, second��*\secondoftwo�
       \fi
}
a) \ifempty{abc}{vide}{pas vide}\qquad
b) \ifempty{}{vide}{pas vide}\qquad
c) \ifempty{ }{vide}{pas vide}\qquad
d) \ifempty{\empty}{vide}{pas vide}�\defline\bbb�/

\begin{exercice}\label{argument.vide}
Expliquer pourquoi le test est n�gatif � la ligne \no\bbb{} du code ci-dessous
\solution
La ligne \no\aaa{} effectue l'action suivante :

\centrecode-\def\tempa{\empty}-

Le test \verb|\ifx\tempa\empty| compare donc les deux textes de remplacement de ces macros qui sont \idx\empty pour la premi�re et un texte vide pour la seconde. Ces deux textes de remplacement ne sont pas �gaux ce qui explique que le test est n�gatif.
\end{exercice}

La macro �\ifempty fonctionne parfaitement, mais elle n'est \emph{pas} purement d�veloppable � cause de la pr�sence du \idx\def dans son texte de remplacement. Pour rendre la macro d�veloppable, l'astuce consiste � utiliser le fait que lorsqu'un argument \verb|#1| d'une macro est vide, tout se passe comme s'il n'existait pas dans son texte de remplacement.  Dans ce cas, les tokens qui sont juste avant et juste apr�s \verb|#1| deviennent cons�cutifs. Il suffit que ces deux tokens soient les m�mes (par exemple �\verb|_|�) pour que le test �\verb|\ifx_#1_|� devienne positif lorsque \verb|#1| est vide :

\showcode/\def\empty{}
\long\def\ifempty#1{%��*\firstoftwo�*\secondoftwo�*\ifempty�
 \ifx_#1_\expandafter\firstoftwo
 \else\expandafter\secondoftwo
 \fi}
a) \ifempty{abc}{vide}{pas vide}\qquad
b) \ifempty{}{vide}{pas vide}\qquad
c) \ifempty{ }{vide}{pas vide}\qquad
d) \ifempty{\empty}{vide}{pas vide}\qquad
e) \edef\foo{\ifempty{abc}{vide}{pas vide}}\meaning\foo/

Bien �videmment, au lieu de �\verb-_-�, nous aurions aussi pu utiliser �\verb-|-�, \idx\empty ou tout autre token. La macro fonctionne bien, mais il va se trouver des cas particuliers o� elle va donner des faux positifs ! En effet, le test \verb-\ifx<token>#1<token>- est vrai si \verb|#1| est vide, mais il sera \emph{aussi} vrai si \verb-#1- commence par le \verb|<token>|. Nous pouvons l'observer ici o� �\verb|W|� est pris comme token de comparaison qui, contrairement � �\verb|_|� peut �tre \emph{affich�} par \TeX{}. Le cas \no4 met en �vidence le probl�me :

\showcode/\long\def\ifempty#1{%��*\firstoftwo�*\secondoftwo�*\ifempty�
 \ifx W#1W\expandafter\firstoftwo
 \else    \expandafter\secondoftwo
 \fi}
1) \ifempty{foobar}{vide}{pas vide}\qquad
2) \ifempty{}{vide}{pas vide}\qquad
2) \ifempty{\empty}{vide}{pas vide}\qquad
4) \ifempty{Wagons}{vide}{pas vide}/

On peut observer que le test \verb|\ifx| a compar� le �\verb|W|� qui le suit et le �\verb|W|� de � \verb|Wagons|�. Comme il est vrai, tout ce qui est jusqu'au \verb|\else| a �t� affich�.

Pour se pr�munir de cet inconv�nient, la m�thode la plus commun�ment utilis�e consiste � \emph{d�tok�niser} l'argument \verb|#1| et l'entourer de deux tokens qui ne sont pas de catcode 12 (\idx\relax est habituellement utilis� dans ce cas). Pour que cela fonctionne, �\verb|\detokenize{#1}|� doit �tre d�velopp� avant que le test n'entre en jeu et n�cessite donc un pont d'\idx\expandafter :

\centrecode-\expandafter\ifx\expandafter\relax\detokenize{#1}\relax-

Avec cette m�thode, le test n'est positif \emph{que} lorsque \verb|#1| est vide. En effet,

\begin{enumerate}
       \item si \verb|#1| commence par un espace, \verb|\detokenize{#1}| se d�veloppe en un espace (de catcode 10) suivi d'autres tokens. Le test se fera donc entre \idx\relax et \verb*| | et sera faux;
       \item si \verb|#1| commence par un autre token, le d�veloppement de \idx\detokenize\verb|{#1}| commence par un caract�re de catcode 12. La comparaison entre \idx\relax et ce token est fausse ;
       \item enfin, si \verb|#1| est vide, \verb|\detokenize{}| se d�veloppe en 0 token et donc, les primitives \idx\relax deviennent cons�cutives et sont vues �gales par le test \tidx{ifx} qui est alors positif.
\end{enumerate}

\showcode/\long\def\ifempty#1{%��*\firstoftwo�*\secondoftwo�*\ifempty�
       \expandafter\ifx\expandafter\relax\detokenize{#1}\relax�\idx*\detokenize�
               \expandafter\firstoftwo
       \else
               \expandafter\secondoftwo
       \fi
}
a) \ifempty{abc}{vide}{pas vide}\qquad
b) \ifempty{}{vide}{pas vide}\qquad
c) \ifempty{ }{vide}{pas vide}\qquad
d) \ifempty{\relax}{vide}{pas vide}\qquad
e) \edef\foo{\ifempty{abc}{vide}{pas vide}}\meaning\foo/�*\ifempty[|)]%

Utiliser \idx\detokenize est la seule m�thode d�veloppable qui soit vraiment infaillible, mais elle a le d�savantage d'�tre un peu lourde � �crire, c'est pourquoi on lui pr�f�re souvent

\centrecode-\ifx\empty#1\empty-

\noindent tout en restant conscient des faux positifs qu'elle peut engendrer dans les cas --~le plus souvent improbables~-- o� \verb-#1- commence par la macro \idx\empty ou toute autre macro \idx\let-�gale � \idx\empty.
\grandsaut

\begin {exercice}
\label{reverse}Programmer une macro �\reverse, admettant comme argument un \verb|<mot>| et dont le d�veloppement maximal est le \verb|<mot>| �crit dans l'ordre inverse.

Par exemple, �\reverse\verb|{foobar}| donne �\verb|raboof|�.
\solution
Pour y parvenir, il faut imaginer deux r�servoirs, A et B recevant des caract�res. L'algorithme est le suivant :
\begin{algo}
       \item mettre le \verb|<mot>| dans le r�servoir A et initialiser le r�servoir B � \verb|<vide>| ;
       \item prendre le premier caract�re du r�servoir A et le mettre en \emph{premi�re} position dans le r�servoir B ;
       \item si le r�servoir A n'est pas vide, retourner au point 2.
\end{algo}

Avec des arguments d�limit�s, il est tr�s facile de construire de tels r�servoirs tout en gardant la macro purement d�veloppable. D�cidons pour l'instant que ces d�limiteurs sont des points. La structure des arguments sera donc :

\centrecode-<r�servoir A>.<r�servoir B>.-

\noindent Voici ce que sont les �tapes pour inverser le texte � abcd � :
\begin{center}
       \verb|abcd..|${}\longrightarrow{}$\verb|bcd.a.|${}\longrightarrow{}$\verb|cd.ba.|${}\longrightarrow{}$\verb|d.cba.|${}\longrightarrow{}$\verb|.dcba.|
\end{center}

Le choix du point interdit que le \verb|<mot>| en contienne, ce qui n'est pas absurde en soi. Cependant, pour plus de s�curit�, nous prendrons \verb|\@nil| comme d�limiteur. Le code de la macro �\reverse ne pr�sente aucune difficult� particuli�re :

\showcode/\catcode`\@11
\def\reverse#1{%��*\reverse�
       \ifempty{#1}
               {}% s'il n'y a rien � inverse, ne rien faire
               {\reverse@i#1\@nil\@nil}% initialisation des r�servoirs et appeler \reverse@i
}
\def\reverse@i#1#2\@nil#3\@nil{% #1 est le 1er caract�re du r�servoir A
       \ifempty{#2}% si ce qui reste apr�s ce 1er caract�re est vide��*\ifempty�
               {#1#3}% renvoyer #1#3 qui est le r�sultat final
               {\reverse@i#2\@nil#1#3\@nil}% sinon, recommencer en d�pla�ant #1
                                           % en 1re position du r�servoir B
}
\catcode`\@12
a) \reverse{foobar}\qquad
b) \edef\foo{\reverse{Bonjour}}\meaning\foo\qquad
c) \reverse{Bonjour le monde}\qquad
d) \reverse{Bonjour{ }le{ }monde}��*\reverse�/

Selon la r�gle de la page~\pageref{argument.espace}, les espaces qui ne sont pas entre accolades sont ignor�s lorsque lus comme argument par une macro. Il est donc normal que � Bonjour le monde � donne un r�sultat invers� sans espace.
\end {exercice}

Le simple fait pour pouvoir tester de fa�on fiable si un argument est vide ouvre d�j� la voie � d'autres tests\ldots{}\idx*[|)]{argument!vide}

\subsection{Tester si un code contient un motif}\label{test.code.contient.motif}
Le but est d'�laborer un test qui v�rifie si un \verb-<code>- contient un autre code que l'on appelle \verb-<motif>-. Nous allons tenter d'�crire une macro �\ifin[|(] dont voici la syntaxe :\label{ifin}

\centrecode-\ifin{<code>}{<motif>}{<vrai>}{<faux>}-

\noindent Le code \verb-<vrai>- sera ex�cut� si \verb-<code>- contient \verb-<motif>- et le code \verb|<faux>| le sera dans le cas contraire.

Comme nous l'avions fait avec les macros �\rightof et �\leftof du chapitre \ref{rightof} et \ref{leftof} de la partie 2, nous allons utiliser une macro auxiliaire � arguments d�limit�s. Cette macro \verb-\ifin@i- sera situ�e � l'int�rieur du texte de remplacement de �\ifin de telle sorte qu'elle puisse acc�der aux arguments de �\ifin. Elle aura le \idx{texte de param�tre} suivant :

\centrecode-\def\ifin@i##1#2##2\@nil{code � d�finir}-

\noindent Ainsi, les arguments d�limit�s \verb|##1| et \verb|##2| collectent ce qui se trouve respectivement avant et apr�s le \verb|<motif>| qui est l'argument \verb|#2| de la macro chapeau.

L'id�e est que la macro �\ifin appelle la macro \verb-\ifin@i- de cette fa�on :

\centrecode-\ifin@i#1#2\@nil-

\noindent o� le \verb|<motif>| (argument \verb-#2-) est ajout� apr�s le \verb|<code>| (argument \verb|#1|) afin de satisfaire la macro � argument d�limit� \verb|\ifin@i| m�me dans le cas o� \verb|#1| ne contient pas \verb|#2|. Avec cet appel, de deux choses l'une :

\begin{itemize}
       \item soit \verb-#1- contient d�j� \verb-#2- et donc la premi�re occurrence de \verb-#2- est dans \verb-#1- et nous pouvons donc affirmer que ce qui se trouve apr�s cette premi�re occurrence (qui est l'argument \verb|##2| de \verb|\ifin@i|) n'est pas vide puisqu'au moins constitu� de \verb-#2- que nous avons rajout�;
       \item soit \verb-#1- ne contient pas \verb-#2-, ce qui fait que la premi�re occurrence de \verb-#2- est le \verb-#2- que nous avons ajout� juste devant le \verb|\@nil|. Par cons�quent, ce qui se trouve apr�s cette occurrence est vide.
\end{itemize}

Il suffit donc de tester si ce qui est apr�s la premi�re occurrence de \verb-#2- est vide ou pas, ce que fait la ligne \no4 du code ci-dessous :

\showcode/\catcode`\@11
\def\ifin#1#2{%��*\ifin�
       \def\ifin@i##1#2##2\@nil{% d�finit la macro auxiliaire
               \ifempty{##2}% si ce qu'il y a derri�re le motif est vide��*\ifempty�
                       \secondoftwo% aller � "faux"��*\secondoftwo�
                       \firstoftwo% sinon � "vrai"��*\firstoftwo�
       }%
       \ifin@i#1#2\@nil% appel de la macro auxiliaire
}
\catcode`\@12
a) \ifin{abc\relax1}{bc}{vrai}{faux}\qquad
b) \ifin{abc \relax1}{c\relax}{vrai}{faux}\qquad
c) \ifin{abc \relax1}{ }{vrai}{faux}\qquad
d) \ifin{abc \relax1}{}{vrai}{faux}\qquad
e) \ifin{}{a}{vrai}{faux}/

Le gros inconv�nient des arguments d�limit�s est le d�faut que nous avions signal� avec la macro �\rightof � la page~\pageref{rightof.et.accolades}. Le \verb|<motif>| ne peut pas contenir d'accolades ouvrantes puisqu'elles se retrouveraient dans le texte de param�tre de \verb|\ifin@i| et en fausseraient la d�finition. Nous allons donc nous limiter � un code et un motif sans accolades\ldots{} Avant de trouver mieux !�*\ifin[|)]

\begin{exercice}\label{ifstart}
�crire une macro �\ifstart[|(] de syntaxe

\centrecode-\ifstart{<code>}{<motif>}{<vrai>}{<faux>}-

\noindent qui teste si le \verb|<code>| commence par le \verb|<motif>| et ex�cute \verb|<vrai>| si c'est le cas et \verb|<faux>| sinon.
\solution
La m�thode est tr�s similaire � celle d�ploy�e dans �\ifin. Dans l'homologue de \verb-\ifin@i- qui est \verb|\ifstart@i|, il suffira de tester si ce qui est \emph{avant} la premi�re occurrence du motif (c'est-�-dire \verb-##1-) est vide ou pas. Ce qui donne ce code :

\showcode/\catcode`\@11
\def\ifstart#1#2{%
       \def\ifstart@i##1#2##2\@nil{\ifempty{##1}}%��*\ifempty�
       \ifstart@i#1#2\@nil
}
\catcode`\@12
a) \ifstart{abc}{bc}{vrai}{faux}\qquad
b) \ifstart{abc}{ab}{vrai}{faux}\qquad
c) \ifstart{ abc}{ }{vrai}{faux}\qquad
d) \ifstart{abc}{}{vrai}{faux}\qquad
e) \ifstart{}{a}{vrai}{faux}/

Les deux derniers cas sont probl�matiques. Il serait logique que l'avant-dernier soit vrai puisque �\verb|abc|� commence bien par un argument vide. Pour le dernier au contraire, il faudrait qu'il soit faux, car un argument vide ne contient pas le motif �\verb|a|�.

Pour faire en sorte qu'un \verb|<motif>| vide donne toujours le code \verb|<vrai>|, il suffit � la ligne \no4 de tester si \verb|#2| est vide et ex�cuter �\firstoftwo si c'est le cas et appeler \verb-\ifstart@i- sinon :

\centrecode-\ifempty{#2}\firstoftwo{\ifstart@i#1#2\@nil}-

Si le \verb|<code>| est vide, l'appel � \verb-\ifstart@i- est \verb-\ifstart@i#2\@nil- et donc, l'argument d�limit� \verb-##1- de \verb-\ifstart@i- est logiquement vide. On peut artificiellement le remplir en mettant un \idx\relax juste avant le \verb-#2- de la ligne 4. Cela donne le code :

\showcode/\catcode`\@11
\def\ifstart#1#2{%
       \def\ifstart@i##1#2##2\@nil{\ifempty{##1}}%��*\ifempty�
       \ifempty{#2}% si motif vide��*\ifempty�
               \firstoftwo% ex�cuter code "vrai"��*\firstoftwo�
               {\ifstart@i#1\relax#2\@nil}% sinon, aller � la macro auxiliaire
}
\catcode`\@12
a) \ifstart{abc}{bc}{vrai}{faux}\qquad
b) \ifstart{abc}{ab}{vrai}{faux}\qquad
c) \ifstart{ abc}{ }{vrai}{faux}\qquad
d) \ifstart{abc}{}{vrai}{faux}\qquad
e) \ifstart{}{a}{vrai}{faux}/
�*\ifstart[|)]\end{exercice}

\subsection{Tester si un code se termine par un motif}
Il est bien plus difficile de tester si un \verb|<code>| se termine par un \verb|<motif>|. Cela est d� � la fa�on qu'ont de fonctionner les arguments d�limit�s qui ne s'int�ressent qu'� la \emph{premi�re} occurrence d'un d�limiteur et non pas � la derni�re. Si nous souhaitons �crire une macro �\ifend[|(] dont la syntaxe est

\centrecode-\ifend{<code>}{<motif>}{<vrai>}{<faux>}-

\noindent nous allons devoir recourir � un algorithme r�cursif.

\begin{algo}
       \item ajouter le \verb|<motif>| au d�but du \verb|<code>| et dans le r�sultat obtenu,
       \item appeler \verb|<code>| ce qui est apr�s la premi�re occurrence du \verb|<motif>|;
       \item si \verb|<code>| est vide ex�cuter \verb|vrai|;
       \item sinon
       \begin{algo}
               \item si \verb|<code>| contient le \verb|<motif>|, retourner en 2;
               \item sinon, ex�cuter \verb|faux|.
       \end{algo}
\end{algo}

Le point \no1 sera l'appel initial � une macro auxiliaire r�cursive \verb|\ifend@i| � argument d�limit�. Cette macro occupera les points suivants (de 2 � 4).

Traduisons cet algorithme en code \TeX{} et v�rifions qu'il fonctionne sur quelques exemples. Le point 1 sera cod� de cette fa�on :

\centrecode-\ifend@i#2#1\@nil-

La macro auxiliaire \verb-\ifend@i- va se charger, gr�ce � son argument d�limit�, d'isoler ce qui se trouve apr�s la premi�re occurrence de \verb|<motif>|. Voici ce que sera son \idx{texte de param�tre} :

\centrecode-\def\if@end##1#2##2\@nil{...}-

\noindent � l'int�rieur de la macro \verb|\if@end|, il suffira de tester si \verb-##2- est vide auquel cas, �\firstoftwo sera ex�cut�. Dans le cas contraire, il faudra tester avec �\ifin si le \verb|##2| contient le \verb|<motif>| qui est \verb|#2| et appeler r�cursivement \verb|\ifend@i| dans l'affirmative et ex�cuter �\secondoftwo sinon :

\showcode/\catcode`\@11
\def\ifend#1#2{%
       \def\ifend@i##1#2##2\@nil{% ##2 = ce qui reste apr�s le motif
               \ifempty{##2}% si ##2 est vide��*\ifempty�
                       \firstoftwo% ex�cuter l'argument "vrai"�\defline\bbb�*\firstoftwo�
                       {\ifin{##2}{#2}% sinon, si ##2 contient le <motif>��*\ifin�
                               {\ifend@i##2\@nil}% appeler \ifend@i avec ce qui reste
                               \secondoftwo% sinon, ex�cuter l'argument "faux"��*\secondoftwo�
                       }%
       }%
       \ifend@i#2#1\@nil% appelle la macro r�cursive�\defline\aaa�
}
\catcode`\@12
1) \ifend{abc de}{de}{vrai}{faux}\qquad
2) \ifend{abd de }{de}{vrai}{faux}\qquad
3) \ifend{abc de }{ }{vrai}{faux}\qquad
4) \ifend{}{a}{vrai}{faux}\qquad
5) \ifend{abc de}{}{vrai}{faux}/

\begin{exercice}
Expliquer pourquoi le code ci-dessus renvoie le contraire de ce que l'on attend aux cas \nos4 et 5 et proposer des solutions pour y rem�dier.
\solution
Dans le cas o� le \verb|<code>| est vide (cas \no4), l'appel de la ligne \no\aaa{} devient

\centrecode-\ifend@i a\@nil-

\noindent et l'argument \verb|##2| de \verb|\ifend@i| qui se trouve apr�s la premi�re occurrence de �\verb|a|� est vide. Pour s'en pr�munir, nous pouvons artificiellement meubler avec \idx\relax ce qui se trouve apr�s cette premi�re occurrence. L'appel � la ligne \no\aaa{} deviendrait donc :

\centrecode-\ifend@i#2\relax#1\@nil-

Pour le cas \no5, le \verb|<motif>| est vide, l'appel de la ligne \no\aaa{} est

\centrecode-\ifend@i abc de\@nil-

\noindent et le texte de param�tre de \verb|\ifend@i| est �\verb-\def\ifend@i##1##2\@nil{...}-� ce qui signifie que l'argument \verb|##1| n'est plus un argument d�limit� : il devient le premier argument (ici �\verb|a|�) et \verb|##2| est le reste jusqu'au \verb|\@nil| (c'est-�-dire �\verb|bc de|�). Continuons � faire fonctionner la macro mentalement : le test �\ifempty\verb|{##2}| est faux, le test suivant �\ifin\verb|{##2}{#2}| est faux aussi puisque \verb|##2| est vide : la macro �\secondoftwo va donc ex�cuter le code \verb|faux|.

Le meilleur rem�de est sans doute de tester d�s le premier appel (ligne \no\aaa) si \verb|#2| est vide, cas o� �\firstoftwo doit �tre ex�cut�.

\showcode/\catcode`\@11
\def\ifend#1#2{%
       \def\ifend@i##1#2##2\@nil{% ##2 = ce qui reste apr�s le motif
               \ifempty{##2}% si ##2 est vide��*\ifempty�
                       \firstoftwo% ex�cuter l'argument "vrai"��*\firstoftwo�
                       {\ifin{##2}{#2}% sinon, si ##2 contient le <motif>��*\ifin�
                               {\ifend@i##2\@nil}% appeler \ifend@i avec ce qui reste
                               \secondoftwo% sinon, ex�cuter l'argument "faux"��*\secondoftwo�
                       }%
       }%
       \ifempty{#2}% si le motif est vide��*\ifempty�
               \firstoftwo% ex�cuter "vrai"��*\firstoftwo�
               {\ifend@i#2\relax#1\@nil}% sinon, appelle la macro r�cursive
}
\catcode`\@12
1) \ifend{abc de}{de}{vrai}{faux}\qquad
2) \ifend{abd de }{de}{vrai}{faux}\qquad
3) \ifend{abc de }{ }{vrai}{faux}\qquad
4) \ifend{}{a}{vrai}{faux}\qquad
5) \ifend{abc de}{}{vrai}{faux}/
�*\ifend[|)]\end{exercice}

\subsection{Remplacer un motif par un autre}\substin
Nous allons maintenant construire une macro �\substin[|(], capable de remplacer un \verb|<motif1>| par un \verb|<motif2>| dans un \verb|<code>| :

\centrecode-\substin{<code>}{<motif1>}{<motif2>}-

La m�thode va consister � parcourir le \verb|<code>| un peu de la m�me fa�on que nous le faisions avec la macro �\ifend. Voici l'algorithme :

\begin{algo}
       \item si le \verb|<code>| est vide, ne rien faire et fin du processus;
       \item sinon
       \begin{algo}
               \item si le \verb|<code>| contient le \verb|<motif1>|, aller au point \no3;
               \item sinon afficher le \verb|<code>| et fin du processus;
       \end{algo}
       \item afficher la partie du \verb|<code>| qui se trouve avant la 1\iere{} occurrence de \verb|<motif1>|;
       \item afficher \verb|<motif2>|;
       \item retourner au point \no1 en appelant \verb|<code>| ce qui se trouve apr�s \verb|<motif1>|.
\end{algo}

Les points \nos1 et 2 vont �tre effectu�s par une macro auxiliaire dont le seul argument non d�limit� sera le
\verb|<code>| en cours d'examen. Les points \nos3 � 5 seront d�volus � une autre macro auxiliaire qui elle, sera � argument d�limit� puisqu'il faut s�parer ce qui se trouve avant et apr�s le \verb|<motif1>|. Voici ce que cela donne en \idx{pseudocode} :

\begingroup
\numalgofalse
\def\algoleftskip{.1\hsize}
\def\algorightskip{.1\hsize}\label{algo2}
\algorithm[\#]{Remplacer toutes les occurrences d'un motif}|
macro ~substin~#1#2#3% #1=<code>, #2=<motif1>, #3=<motif2>
       macro ~substin@i~##1
               ~si~ ##1 est vide
                       relax% ne rien faire
               ~sinon~
                       ~si~ ##1 contient #3
                               ~substin@ii~##1@nil% appeler la macro � argument d�limit�s
                       ~sinon~
                               ##1% afficher le <code>
                       ~finsi~
               ~finsi~
       ~fin~\medbreak
       macro ~substin@ii~##1#2##2@nil% ##1 et ##2=ce qui est avant/apr�s <motif1>
               afficher "##1#3"
               appeler ~substin@i~(##2)% puis recommencer avec le code qui reste
       ~fin~\medbreak
       appeler ~substin@i~(#1)% engage le processus
~fin~|
\endgroup

La traduction de ce \idx{pseudocode} en \TeX{} ne pose pas de probl�me particulier :

\showcode/\catcode`\@11
\def\substin#1#2#3{%
       \def\substin@i##1{%
               \ifempty{##1}% si le <code> est vide��*\ifempty�
                       \relax% ne rien faire -> fin du processus
                       {\ifin{##1}{#2}% sinon, si le <code> contient <motif1>��*\ifin�
                               {\substin@ii##1\@nil}% appeler la macro � argument d�limit�s
                               {##1}% sinon, afficher le <code>
                       }%
       }%
       \def\substin@ii##1#2##2\@nil{%
               ##1#3% afficher ##1 et #3 (qui est <motif2>)
               \substin@i{##2}% et recommencer avec ce qui reste
       }%
       \substin@i{#1}%
}
\catcode`\@12
a) \substin{abracadabra}{a}{A}\qquad
b) \substin{abracadabra}{x}{W}\qquad
c) \substin{abracadabra}{br}{}\qquad
d) \substin{1\relax3}\relax{222}\qquad/�*\substin[|)]

\begin{exercice}
Modifier cette macro en une macro �\substtocs[|(] pour qu'elle n'affiche pas le r�sultat, mais le mette dans le texte de remplacement d'une \verb|\<macro>| dont l'utilisateur pourra choisir le nom :

\centrecode-\substtocs\<macro>{<code>}{motif1}{motif2}-

\solution
Au lieu d'afficher des morceaux de code, il faudra les ajouter au texte de remplacement d'une macro charg�e de collecter le code r�sultant de ces substitutions. Pour ajouter du code au texte de remplacement d'une macro, �\addtomacro, programm�e � la page~\pageref{addtomacro} sera utile.

\showcode/\catcode`\@11
\def\substtocs#1#2#3#4{%
       \def\substtocs@i##1{%
               \ifempty{##1}% si le <code> est vide��*\ifempty�
                       \relax% ne rien faire -> fin du processus
                       {\ifin{##1}{#3}% sinon, si le <code> contient <motif1>��*\ifin�
                               {\substtocs@ii##1\@nil}% appeler la macro � argument d�limit�s
                               {\addtomacro#1{##1}}% sinon, ajouter le <code>��*\addtomacro�
                       }%
       }%
       \def\substtocs@ii##1#3##2\@nil{%
               \addtomacro#1{##1#4}% ajouter ##1#4��*\addtomacro�
               \substtocs@i{##2}% et recommencer avec ce qui reste
       }%
       \let#1=\empty% initialise la macro � vide�\idx*\empty�
       \substtocs@i{#2}%
}
\catcode`\@12
\substtocs\foo{abracadabra}{a}{A}\meaning\foo\par
\substtocs\foo{abracadabra}{x}{W}\meaning\foo\par
\substtocs\foo{abracadabra}{br}{}\meaning\foo\par
\substtocs\foo{1\relax3}\relax{222}\meaning\foo\par
\substtocs\foo{\ifnum1=2 test vrai\fi}{2}{1}\meaning\foo/
\end{exercice}�*\substtocs[|)]

\begin{exercice}\label{exo.majuscules}
�crire une macro �\majmot[|(]\verb|{<phrase>}| qui met en majuscule tous les mots de la \verb|phrase|.
\solution
Pour que �\majmot effectue son travail, dans la \verb|<phrase>|, chaque espace doit �tre remplac� par �\verb*| \majuscule|�, o� la macro �\majuscule lit un argument (qui sera la lettre du mot suivant) et la met en majuscule. En coulisses, nous utiliserons la primitive \idx\uppercase.

Nous allons mettre �\substin � contribution pour effectuer ces remplacements, en ayant pris soin de mettre �\majuscule tout au d�but de la phrase afin de traiter la premi�re lettre du premier mot.

\showcode/\def\majuscule#1{\uppercase{#1}}�\idx*\uppercase�*\majuscule�
\def\majmot#1{\substin{\majuscule#1}{ }{ \majuscule}}��*\substin�*\majuscule�
\majmot{un petit texte}\par
\majmot{Un grand texte sans importance}/

Conclusion : �a ne fonctionne pas du tout !

Une petite analyse montre que tout vient de la fa�on dont est faite la substitution et il faut revenir au code de �\substin :

\begingroup
\renewcommand*\indentcodeactivechars[1]{%
       \defactive\^^M{\par\hspace{#1}}%
       \defactive\^^I{{ }{ }}% tab = 4 espaces
       \catcode`\�=13
       \begingroup
               \lccode`\~`\�\relax
               \lowercase{\endgroup\long\def~##1~}{%
                       \begingroup
                               \catcode`\{=1 \catcode`\}=2 \catcode`\#=6 \catcode`\\=0 \catcode`\$=3
                               \catcode`\f=11
                               \endlinechar=-1
                               \scantokens{##1}%
                       \endgroup
                       }% �chappement �...�
       \footnotesize
}\indencodenumtrue
\indentcode/\def\substin#1#2#3{%��*\substin�
       \def\substin@i##1{%
               \ifempty{##1}% si le code est vide��*\ifempty�
                       \relax% ne rien faire -> fin du processus
                       {\ifin{##1}{#2}% sinon, si le code contient motif1��*\ifin�
                               {\substin@ii##1\@nil}% appeler la macro � argument d�limit�s
                               {##1}% sinon, afficher le code
                       }%
       }%
       \def\substin@ii##1#2##2\@nil{%
               ##1#3% afficher ##1 et #3 (qui est <motif2>)
               \substin@i{##2}% et recommencer avec ce qui reste
       }%
       \substin@i{#1}%
}/\endgroup

Constatons � ligne \no11 que le code \verb|#2| est substitu� par le motif \verb|#3| donc, \verb|##1#3| est ex�cut� par \TeX{} dans la foul�e. C'est de cette ex�cution \emph{au fur et � mesure} que vient le probl�me. Ici en effet, le motif de substitution \verb|#3| est �\verb*| \majsucule|�. Notre processus �choue parce que lors de l'ex�cution au fur et � mesure, la macro �\majuscule va lire son argument qui est \verb|\substin@i| de la ligne \no12. Cet argument sera trait� par \idx\uppercase qui le laisse intact puisque \idx\uppercase n'a aucun effet sur les s�quences de contr�le. Le code ci-dessus ne produit donc aucun effet.

Nous allons nous en sortir en utilisant la macro �\substtocs de fa�on � stocker le code obtenu dans une macro temporaire \verb|\temp| que nous afficherons � la toute fin du processus, avant de sortir du groupe semi-simple dans lequel elle a �t� cr��e :

\showcode/\def\majuscule#1{\uppercase{#1}}�\idx*\uppercase�*\majuscule�
\def\majmot#1{%
       \begingroup�\idx*\begingroup�
               \substtocs\temp{\majuscule#1}{ }{ \majuscule}%��*\substtocs�*\majuscule�
               \temp% ex�cute la macro temporaire
       \endgroup�\idx*\endgroup�
}
\majmot{un petit texte}\par
\majmot{Un grand texte Sans importance}/

La le�on � retenir ici est que faire ex�cuter par \TeX{} de morceaux de code dans une macro r�cursive n'est pas �quivalent � les mettre tous dans une s�quence de contr�le que l'on ex�cute en une fois � la fin.�*\majmot[|)]
\end{exercice}

\begin{exercice}
�crire une macro �\cnttimes[|(]\label{cnttimes}\verb|{<code>}{<motif>}| qui affiche combien de fois le \verb|<motif>| est contenu dans le \verb|<code>|.
\solution
Nous allons proc�der comme dans �\substtocs. La macro chapeau initialisera un compteur � 0 et passera la main � une macro auxiliaire, charg�e de l'incr�menter � chaque fois que le motif sera rencontr� :

\showcode/\catcode`\@11
\newcount\cnt@occ�\idx*\newcount�
\def\cnttimes#1#2{%��*\cnttimes�
       \def\cnttimes@i##1{%
               \ifempty{##1}% si le <code> est vide��*\ifempty�
                       {\number\cnt@occ}% afficher le nombre d'occurrences�\idx*\number�
                       {\ifin{##1}{#2}% sinon, si le <code> contient <motif1>��*\ifin�
                               {\cnttimes@ii##1\@nil}% appeler la macro � argument d�limit�s
                               {\number\cnt@occ}% sinon, afficher le nombre d'occurrences
                       }%
       }%
       \def\cnttimes@ii##1#2##2\@nil{%�\idx*\advance�
               \advance\cnt@occ1
               \cnttimes@i{##2}% et recommencer avec ce qui reste
       }%
       \cnt@occ=0 % initialise le compteur
       \cnttimes@i{#1}%
}
\catcode`\@12
a) \cnttimes{abracadabra}{a}\qquad
b) \cnttimes{abracadabra}{ra}\qquad
c) \cnttimes{abracadabra}{w}\qquad
d) \cnttimes{abc def ghijk l }{ }\qquad
e) \cnttimes{\ifnum1=2 vrai\else faux\fi}{\ifnum}��*\cnttimes�/�*\cnttimes[|)]

Juste pour le plaisir de se compliquer la vie, essayons de modifier la macro en �\cnttimestocs[|(] pour qu'elle r�ponde aux contraintes suivantes :

\begin{enumerate}
       \item ne pas utiliser de compteur;
       \item n'�crire qu'une seule macro int�rieure au lieu de deux;
       \item stocker le r�sultat dans une macro sp�cifi�e par l'utilisateur.
\end{enumerate}

Si nous nous interdisons l'utilisation d'un compteur, nous devrons recourir � la primitive \idx\numexpr pour remplacer \idx\advance afin d'incr�menter le nombre d'it�rations. Il est �videmment possible de stocker le nombre d'it�rations dans une s�quence de contr�le, mais dans ce cas, se priver d'un compteur pour basculer vers une macro n'a pas vraiment de sens, autant conserver un compteur. Il est plus original de stocker le nombre d'it�rations dans un argument qui s'ajoutera � ceux de la macro r�cursive \verb|\cnttimes@i| vue dans le code pr�c�dent. Pour pouvoir facilement incr�menter cet argument (qui implique le 1-d�velopper) avant de lancer l'appel r�cursif, il est judicieux de le placer comme premier argument. L'id�e la plus pratique est donc d'ajouter cet argument (et de le d�limiter par un \verb|\@nil|) avant ceux de \verb-\cnttimes@ii-. La macro r�cursive \verb|\cnttimestocs@i| aura donc le texte de param�tre suivant :

\centrecode-\def\cnttimestocs@i##1\@nil##2#2##3\@nil{...}-

\noindent Il faudra sp�cifier �\verb|0|� comme argument \verb|##1| lors du premier appel.

Ensuite, comme cette macro r�cursive � est � argument d�limit� par le \verb|<motif>|, elle \emph{doit} recevoir un \verb|<code>| qui contient ce \verb|<motif>|. Il est donc n�cessaire de tester la pr�sence de ce \verb|<motif>| lors du premier appel et �galement � l'int�rieur de la macro r�cursive avant qu'elle ne s'appelle elle-m�me avec le \verb|<code>| restant.

\showcode|\catcode`\@11
\long\def\cnttimestocs#1#2#3{% #3=macro recevant le r�sultat��*\cnttimestocs�
       \long\def\cnttimestocs@i##1\@nil##2#2##3\@nil{%
               % ##1=nb d'occurrences rencontr�es jusqu'alors
               % ##2 et ##3=ce qui est avant/apr�s le <motif>
               \ifin{##3}{#2}% si le <motif> est dans ce qui reste��*\ifin�
                       {\expandafter\cnttimestocs@i% appeler la macro r�cursive
                               \number\numexpr##1+1\relax\@nil% avec une occurrence de plus�\idx*\number\idx*\numexpr�
                               ##3\@nil% et ce qui reste
                       }%
                       {\edef#3{\number\numexpr##1+1\relax}}% sinon, stocker 1 occurrence de plus dans #3
       }%
       \ifin{#1}{#2}% si le <motif> est dans le <code>��*\ifin�
               {\cnttimestocs@i 0\@nil#1\@nil}% appeler la macro r�cursive avec 0 occurrence
               {\def#3{0}}% sinon, mettre 0 dans #3
}
\catcode`\@12
a) \cnttimestocs{abracadabra}{a}\foo \meaning\foo\qquad
b) \cnttimestocs{abracadabra}{ra}\foo \meaning\foo\qquad
c) \cnttimestocs{abracadabra}{w}\foo \meaning\foo\qquad
d) \cnttimestocs{abc def ghijk l }{ }\foo \meaning\foo\qquad
e) \cnttimestocs{\ifnum1=2 vrai\else faux\fi}{\ifnum}\foo \meaning\foo|
�*\cnttimestocs[|)]\end{exercice}

\subsection{Substitutions successives}
Nous allons maintenant �crire une macro �\multisubst[|(], g�n�ralisation de la macro �\substin o� nous pourrons sp�cifier plusieurs substitutions successives :

\centrecode-\multisubst{<code>}{{<motif1>}{<motif2>}{<motif3>}{<motif4>}{<motif5>}...}-

\noindent Cette macro substituera toutes les occurrences de \verb|<motif1>| par \verb|<motif2>| puis toutes celles de \verb|<motif3>| par \verb|<motif4>| et ainsi de suite jusqu'� ce que la liste des substitutions soit vide dans le deuxi�me argument. Les motifs utilis�s dans la substitution seront donc lus par \emph{paires}. L'id�e est de se servir de la macro �\substin pr�c�demment �crite en lui envoyant comme second et troisi�me argument les motifs de substitution pris deux par deux dans la liste. Comme un espace non entour� d'accolades est ignor� en tant qu'argument, les motifs peuvent �tre group�s par paires \emph{s�par�es par un espace} dans la liste des motifs afin d'en am�liorer la lisibilit�.

\showcode/\catcode`\@11
\def\multisubst#1#2{%
       \def\subst@code{#1}% stocke le <code>
       \multisubst@i#2\@nil% appelle la macro r�cursive avec la liste de motifs
}

\def\multisubst@i#1#2#3\@nil{% #1 et #2=paire de motifs  #3=motifs restants
       \expandafter\substtocs\expandafter\subst@code\expandafter% 1-d�veloppe��*\substtocs�
               {\subst@code}{#1}{#2}% le <code> et effectue la substitution en cours
       \ifempty{#3}% si la liste des motifs est vide��*\ifempty�
               \subst@code% ex�cuter le <code> obtenu
               {\multisubst@i#3\@nil}% recommencer avec les motifs qui restent
}
\catcode`\@12
1) \multisubst{abracadabra}{aA rR}\par
2) \multisubst{Ce texte devenu \`a peine reconnaissable montre que le�\defline\aaa�
  r\'esultat contient des sonorit\'es catalanes, corses ou grecques
  assez inattendues.}{a{AA} ya uy ou io ei {AA}e}/

La macro chapeau \verb|\multisubst| de la ligne \no2 se contente de lire le \verb|<code>| et l'assigne � la macro \verb|\subst@code| avant de passer la main � la v�ritable macro r�cursive \verb|\multisubt@i|, � argument d�limit�. La liste des motifs de substitutions est pass�e comme argument pour s'�tendre jusqu'au \verb|\@nil|. Les arguments non d�limit�s \verb|#1| et \verb|#2| deviennent les deux motifs de substitution de l'it�ration en cours tandis que \verb|#3| est la liste des paires restantes.

Le cas \no2 des lignes \nos\aaa{} � \number\numexpr\aaa+2\relax{} traite d'une fa�on diff�rente le probl�me de la permutation circulaire des voyelles d�j� r�solu � la page~\pageref{permutation.voyelles}. On ne touche plus � aucun code de cat�gorie, mais on effectue tour � tour les substitutions d�sir�es. La m�thode est cependant \emph{lente}, car l'argument est ici un texte assez long et celui-ci sera parcouru par �\multisubst autant de fois qu'il y a de substitutions � faire, c'est-�-dire 7 fois. La � propret� � que l'on gagne � ne pas modifier les codes de cat�gorie se paie en lenteur.
\grandsaut

Au-del� ce ce d�faut li� � la m�thode utilis�e, le code pr�sente une autre redondance : chaque paire est lue \emph{plusieurs fois}. Elle est lue une premi�re fois par la macro chapeau \verb|\multisubst| puisqu'elle lit toutes les paires. Par la suite, � chaque it�ration, la macro r�cursive \verb|\multisubst@i| lit (et mange) la premi�re paire de son argument, mais lit \emph{aussi que la totalit� des paires restantes}. La totalit� des paires est donc lue deux fois : une fois par la macro chapeau et une fois par la macro r�cursive lors de la premi�re it�ration (qui ensuite supprime la paire \no1). � la 2\ieme{} it�ration, la macro r�cursive lit la totalit� des paires restantes et supprime la paire \no2, etc. Ainsi, s'il y a $n$ paires, la premi�re est lue 2 fois, la 2\ieme{} est lue 3 fois, et ainsi de suite jusqu'� la $n$\ieme{} qui est lue $n+1$ fois.

Il s'agit donc de changer de m�thode afin de limiter le nombre de lectures des paires. Envisageons le sc�nario suivant :

\begin{itemize}
\item lire la liste de toutes les paires une fois afin de les transmettre � la macro r�cursive en les faisant suivre d'une paire sp�ciale, constitu�e de deux arguments sp�ciaux;
\item cette macro r�cursive, au lieu de lire tous les arguments, n'en lit que deux : pour savoir si elle doit les prendre comme une paire de motifs ou comme condition d'arr�t, il faut qu'elle les teste et les compare aux arguments sp�ciaux;
\item si le test est positif, cela signifie que la fin de la liste des couples de motifs a �t� compl�tement lue et que la fin du processus doit �tre ex�cut�e;
\item dans le cas d'un test n�gatif, la substitution est ex�cut�e et la macro s'appelle elle m�me pour une nouvelle it�ration.
\end{itemize}

Cette fa�on de proc�der implique que chaque paire est lu exactement deux fois; une fois par la macro chapeau et une fois par la macro r�cursive.

Un dernier d�tail doit �tre d�cid� : que sont des arguments \emph{sp�ciaux}? Ce sont des arguments qui ne sont pas susceptibles d'�tre un des deux motifs. Tout est imaginable, mais il semble assez s�r de prendre un \idx{quark} tant ce genre de macro est improbable dans une liste de motifs de substitution. Voici comment modifier le code :

\showcode/\catcode`\@11
\def\quark{\quark}��*\quark�

\def\multisubst#1#2{% #1 = <code>   #2 = <liste des paires>
       \def\subst@code{#1}% stocke le <code>
       \multisubst@i#2\quark\quark% appelle la macro r�cursive avec ��*\quark�
                                  % 2 arguments sp�ciaux en fin de liste
}

\def\multisubst@i#1#2{% #1#2 = paire de motifs en cours
       \def\arg@a{#1}% stocke le <motif1> dans une macro
       \ifx\arg@a\quark% si le motif sp�cial est atteint��*\quark�
               \expandafter\subst@code% ex�cuter le code obtenu
       \else
               \expandafter\substtocs\expandafter\subst@code\expandafter% 1-d�veloppe��*\substtocs�
                       {\subst@code}{#1}{#2}% le <code> et effectue la substitution en cours
               \expandafter\multisubst@i% puis lis la paire de motifs suivants
       \fi
}
\catcode`\@12
\multisubst{abracadabra}{aA rR}\par
\multisubst{Ce texte devenu \`a peine reconnaissable montre que le r\'esultat contient des
 sonorit\'es catalanes, corses ou grecques assez inattendues.}{a{AA} ya uy ou io ei {AA}e}/�*\multisubst[|)]

\label{lire.arguments}\begin{regle}[M�thode de programmation]
       Lorsqu'une liste d'arguments cons�cutifs doit �tre lue au fur et � mesure par une macro r�cursive, deux m�thodes de lecture sont envisageables. Elles ont en commun une premi�re lecture de tous les arguments afin de les passer � la macro r�cursive et c'est cette derni�re qui a deux fa�ons de fonctionner :

       \begin{enumerate}
               \item lire la totalit� des arguments restants � chaque it�ration, utiliser ceux qui sont utiles � l'it�ration en cours et recommence1r avec tous les arguments restants. S'arr�ter lorsque la liste d'arguments restants est vide;
               \item ne lire \emph{que} les arguments utiles � l'it�ration en cours, les utiliser et recommencer. S'arr�ter lorsque l'un des arguments lus est �gal � un argument sp�cifique pr�alablement plac� en fin de liste par la macro chapeau.
       \end{enumerate}
       \end{regle}

Il est inutile de dire qu'un programmeur rigoureux choisit de pr�f�rence la deuxi�me m�thode m�me si souvent, le nombre d'arguments � lire est peu �lev� auquel cas la premi�re m�thode est parfaitement acceptable.\tidx*[|)]{ifx}

\section{Autres tests}
\subsection{Pseudotests et variables bool�ennes}\idx*[|(]{pseudotest}
\TeX{} dispose des pseudotests \tidx{iftrue} et \tidx{iffalse}, le premier est toujours vrai et le second toujours faux. Bien qu'elles en partagent la syntaxe et les subtilit�s de d�veloppement, ces primitives n'effectuent pas de tests. Cependant, nous allons le voir un peu plus bas, elles n'en sont pas moins utiles.

\showcode/\iftrue foobar\else ceci n'est jamais lu par \TeX\fi\par
\iffalse ceci n'est jamais lu par \TeX\else foobar\fi/

On peut bien s�r rendre une macro \idx\let-�gale � \tidx{iftrue} ou \tidx{iffalse} pour, au choix, disposer d'une macro simulant un test toujours vrai ou toujours faux. C'est d'ailleurs exactement ce que fait la macro de plain-\TeX{} \idx\newif\verb|<macro>| qui construit 3 macros qui ont un comportement identique � celui de variables � bool�ennes � que l'on trouve dans d'autres langages.

Ainsi, si nous �crivons \idx\newif\verb|\ifbar| alors, 3 s�quences de contr�le seront cr��es :
\begin{itemize}
       \item \verb|\bartrue|  qui rend \verb|\ifbar| \idx\let-�gale � \tidx{iftrue} ;
       \item \verb|\barfalse| qui rend \verb|\ifbar| \idx\let-�gale � \tidx{iffalse} ;
       \item \verb|\ifbar| qui tient lieu de \tidx{iftrue} ou \tidx{iffalse} selon la � valeur bool�enne � qui lui aura �t� donn�e par l'une des deux premi�res macros.
\end{itemize}

\showcode/\newif\ifhomme�\idx*\newif�
\def\debutlettre{Ch\ifhomme er Monsieur\else �re Madame\fi}%

\hommetrue
\debutlettre
\medbreak�\idx*\medbreak�

\hommefalse
\debutlettre/

Le \idx[!plain-\TeX]{format} plain-\TeX{} fait en sorte que lorsqu'on �crit \idx\newif\verb|\<nom>|, le \verb|<nom>| commencer \emph{obligatoirement} par �\verb|if|�. Il est int�ressant de noter que \LaTeX{} r�-impl�mente la macro \idx\newif en autorisant le \verb|<nom>| � commencer par deux caract�res quelconques qui seront enlev�s lorsque \verb|\<nomtrue>| ou \verb|\<nomfalse>| sont cr�es.

\begin{regle}
Les \idx{pseudotest}s \tidx{iftrue} et \tidx{iffalse} n'effectuent aucun test et donc n'admettent aucun argument. Ils sont respectivement toujours vrai et toujours faux. En d�pit de ce caract�re invariable, ils se comportent comme n'importe quel test, notamment en ce qui concerne l'�ventuelle pr�sence du \tidx{else} et celle, obligatoire, du \tidx{fi}.

La macro \idx\newif, suivie d'une macro \verb|\if<nom>| cr�e 3 nouvelles macros dont le comportement est identique � celui des variables bool�ennes. Le test \verb|\if<nom>| sera vrai si la macro \verb|\<nom>true| a �t� ex�cut�e auparavant et sera faux si c'est la macro \verb|\<nom>false|.
\end{regle}\idx*[|)]{pseudotest}

\subsection{Le test \texttt{\textbackslash ifcat}}\tidx*[|(]{ifcat}
Le test \verb|\ifcat<token1><token2>| compare les codes de cat�gorie des deux tokens qui le suivent imm�diatement. Ce test se comporte un peu comme \tidx{ifnum} en ce sens qu'il lance un d�veloppement maximal \emph{avant} de faire le test. Sans action visant � emp�cher le d�veloppement (utilisation de \idx\noexpand ou \idx\unexpanded), le test compare donc les deux premiers tokens non d�veloppables r�sultant du d�veloppement maximal.

Il faut savoir que pour \verb|\ifcat|, un token de type s�quence de contr�le est vu comme ayant un code de cat�gorie �gal � 16. Cette 17\ieme{} cat�gorie, sp�cifique au test \verb|\ifcat|, vient s'ajouter aux 16 autres cat�gories d�j� existantes pour la primitive \idx\catcode. En revanche, si une s�quence de contr�le ou un caract�re actif a �t� pr�alablement rendu \idx\let-�gal � un \verb|<token>|, \verb|\ifcat| prend en compte le code de cat�gorie du \verb|<token>|.

\showcode/\catcode`\*=13 \catcode`\+=13 % "*" et "+" sont actifs
1) \def*{xyz}\def+{abc}% d�finit les caract�res actifs
  \ifcat *+vrai\else faux\fi\qquad �\tidx*{ifcat}�
2) \ifcat \noexpand *\noexpand +vrai\else faux\fi\qquad�\idx*\noexpand�
3) \def\foo{foobar}%
  \ifcat \noexpand\foo\relax vrai\else faux\fi\qquad% \foo et \relax sont vus �gaux   �\idx*\noexpand�
4) \ifcat = vrai\else faux\fi\qquad% "=" et " " n'ont pas le m�me catcode
5) \ifcat _^vrai\else faux\fi\qquad% "_" et "^" n'ont pas le m�me catcode
6) \let\foo=&
  \ifcat &\foo vrai\else faux\fi% "&" et \foo (let-�gal � "&") sont vus �gaux�\tidx*{ifcat}�/

Ce qui arrive lors du test \no1 est facilement compr�hensible : le caract�re actif �\verb-*-� est d�velopp� au maximum pour donner �\verb-xyz-�. Le test \verb|\ifcat| comparera donc les deux premiers tokens issus de ce d�veloppement, �\verb-x-� et �\verb-y-�, et comme ils ont le m�me catcode, le test sera vrai et tout ce qui est avant le \tidx{else} sera ex�cut�. Le �\verb|z|� restant va �tre dirig� vers l'affichage. Ensuite, le caract�re actif �\verb|+|� va se d�velopper et afficher �\verb|abc|�. Enfin, �\verb|vrai|� sera affich�. On obtient bien l'affichage �\verb|zabcvrai|�.

Le \idx\noexpand du test \no3 bloque le d�veloppement de la macro \verb|\foo| et la comparaison qui est faite est bien entre les catcodes de �\verb-\foo-� et �\verb-\relax-�.

\begin{regle}
Le test \verb|\ifcat| lance le d�veloppement maximal et d�s qu'il obtient deux tokens non d�veloppables (ou dont le d�veloppement est bloqu� par \idx\noexpand ou \idx\unexpanded), il effectue la comparaison des codes de cat�gorie.

Si un token test� par \verb|\ifcat| est une s�quence de contr�le ou un caract�re actif rendu \idx\let-�gal � un \verb|<token>|, \verb|\ifcat| prend en compte le code de cat�gorie du \verb|<token>|.

Si un token test� par \verb|\ifcat| est une s�quence de contr�le, son code de cat�gorie est vu �gal � 16.
\end{regle}

\begin{exercice}\label{ifcs}
�crire une macro �\ifcs[|(], de syntaxe

\centrecode|\ifcs<token>{<vrai>}{<faux>}|

qui teste si le \verb|<token>| est une s�quence de contr�le au sens de \verb|\ifcat|. Selon l'issue du test, \verb|<vrai>| ou \verb|<faux>| seront ex�cut�s.
\solution
La comparaison sera faite entre le \verb|<token>| dont on aura bloqu� le d�veloppement et \idx\relax. Voici le code :

\showcode/\catcode`\@11
\def\ifcs#1{%��*\firstoftwo�*\secondoftwo\idx*\noexpand�
       \ifcat\noexpand#1\relax\expandafter\firstoftwo
       \else                  \expandafter\secondoftwo
       \fi
}
\catcode`\@12
1) \def\foo{bar}\ifcs\foo{vrai}{faux}\qquad
2) \ifcs\def{vrai}{faux}\qquad
3) \ifcs A{vrai}{faux}\qquad
\catcode`\*=13
4) \let*=W \ifcs*{vrai}{faux}\qquad
5) \let*=\relax \ifcs*{vrai}{faux}\qquad
6) \let\foo=A \ifcs\foo{vrai}{faux}\qquad
7) \ifcs\bgroup{vrai}{faux}/

Remarquons aux cas \nos5, 6 et 7 que si l'on s'en tient � la vraie d�finition d'une s�quence de contr�le (suite de caract�res qui commence par le caract�re d'�chappement), le test �\ifcs que nous avons �crit n'est pas satisfaisant.
\end{exercice}�*\ifcs[|)]\tidx*[|)]{ifcat}

\subsection{Le test \texttt{\textbackslash if}}\tidx*[|(]{if}
Le test \verb|\if| est en tous points semblable au test \verb|\ifcat| sauf que ce sont les codes de \emph{caract�re} des deux tokens qui sont compar�s.

\begin{regle}
Le test \verb|\if| instaure un d�veloppement maximal et d�s qu'il obtient deux tokens non d�veloppables (ou dont le d�veloppement est bloqu� par \idx\noexpand ou \idx\unexpanded), il effectue la comparaison de leurs codes de caract�re.

Si un token test� par \verb|\if| est une s�quence de contr�le ou un caract�re actif rendu \idx\let-�gal � un \verb|<token>|, \verb|\if| prend en compte le code de caract�re du \verb|<token>|.

Si un token test� par \verb|\if| est une s�quence de contr�le, son code de caract�re est vu �gal � 256.
\end{regle}

\showcode/1) \def\foo{xxy}\def\bar{aab}
  \if\foo\bar vrai\else faux\fi\qquad
2) \if aA vrai\else faux\fi\qquad% "a" et "A" n'ont pas les m�mes charcode
3) \if\relax\noexpand\foo vrai\else faux\fi\qquad% \relax et \foo ont un charcode=256�\idx*\noexpand�
4) \let\foo=&\if\foo &vrai\else faux\fi\qquad% \foo est vue comme "&"
5) \if\string~\noexpand~vrai\else faux\fi�\idx*\string\cidx*\~�/

\begin{exercice}\label{ifcs.la.vraie}
Utiliser le test \verb|\if| pour que la macro �\ifcs[|(]\verb|<token>{<vrai>}{<faux>}| vue pr�c�demment ne renvoie \verb|<vrai>| que si le \verb|<token>| est une s�quence de contr�le, c'est-�-dire lorsqu'il commence par le caract�re d'�chappement.
\solution
Il est in�vitable que nous allons devoir tester le caract�re d'�chappement. Pour cela, nous allons ouvrir un groupe semi-simple et imposer un caract�re d'�chappement avec \idx\escapechar. Nous le prendrons �gal � �\verb|@|� mais tout autre choix conviendrait; l'essentiel est de se pr�munir d'un r�gime sp�cial o� l'\idx\escapechar serait n�gatif ou nul. Il suffit ensuite de tester si les deux caract�res qui se trouvent au d�but de �\idx\string\verb|#1a|� (le �\verb|a|� prot�ge d'un argument vide) et �\idx\string\idx\relax� sont les m�mes. Apr�s avoir ferm� le groupe, les classiques �\firstoftwo ou �\secondoftwo renvoient \verb|<vrai>| ou \verb|<faux>|. Pour isoler le premier caract�re d'une chaine arbitraire, la macro �\firstto@nil sera utilis�e.

\showcode/\catcode`\@11
\def\ifcs#1{%��*\ifcs�
       \begingroup�\idx*\begingroup�
               \escapechar=`\@ % prend "@" comme caract�re d'�chappement�\idx*\escapechar�
               \if% les premiers caract�res de
                       \expandafter\firstto@nil\string#1a\@nil% "#1a"��*\firstto@nil\idx*\string�
                       \expandafter\firstto@nil\string\relax\@nil% et "\relax" sont-ils �gaux ?�\idx*\string�*\firstto@nil�
                       \endgroup\expandafter\firstoftwo% si oui, fermer le groupe et renvoyer "vrai"��*\firstoftwo\idx*\endgroup�
               \else% sinon, fermer le groupe et renvoyer "faux"
                       \endgroup\expandafter\secondoftwo��*\secondoftwo�
               \fi
}
\catcode`\@12
1) \def\foo{bar}\ifcs\foo{vrai}{faux}\qquad
2) \ifcs\def{vrai}{faux}\qquad
3) \ifcs A{vrai}{faux}\qquad
\catcode`\*=13
4) \let*=W \ifcs*{vrai}{faux}\qquad
5) \let*=\relax \ifcs*{vrai}{faux}\qquad
6) \let\foo=A \ifcs\foo{vrai}{faux}\qquad
7) \ifcs\bgroup{vrai}{faux}�\idx*\bgroup�/
�*\ifcs[|)]\end{exercice}\tidx*[|)]{if}

\subsection{Test incomplets}\idx*[|(]{test incomplet}
Entrons � pr�sent au plus profond de la m�canique \TeX ienne des tests et examinons les tests incomplets. Un test est dit incomplet lorsque les choses � comparer sont en nombre insuffisant et font intervenir les primitives du test lui-m�me, � savoir \tidx[|etc]{else} et \tidx[|etc]{fi}.
\grandsaut

Demandons-nous quelle est la comparaison faite dans ce test :

\centrecode-\ifx a\fi-

\noindent Si l'on s'en tient � la d�finition de \tidx{ifx}, le �\verb|a|� est compar� au \verb|\fi| mais ce m�me \verb|\fi|, captur� par la comparaison et d�s lors indisponible, ne casse-t-il pas l'�quilibrage entre le \tidx{ifx} et le \verb|\fi| ?

Dans le m�me ordre d'id�e, que se passe-t-il lors de ce test ?

\centrecode-\ifnum1=2\else3\fi 4-

\noindent Lorsque le \verb|2| est lu, \TeX{} est en train de lire un nombre et se trouve donc en phase de \idx{d�veloppement maximal}. Va-t-il d�velopper le \verb|\else|, puis lire \verb|3| puis poursuivre son d�veloppement et manger le \verb|\fi|? Ensuite, continue-t-il son d�veloppement plus loin avec le 4 et avec ce qui se trouve apr�s ? Le \verb|\else| et le \verb|\fi|, mang�s par la lecture du nombre, rompent-ils l'�quilibrage entre le \tidx{ifnum} et le \verb|\fi| ?

\idx*[!sp�cial|(]{\relax}\begin{regle}
\relax Lorsqu'un \verb|\else| ou un \verb|\fi| appari� avec un test est rencontr� lors de l'�valuation de ce test, \TeX{} ins�re un \verb|\relax| sp�cial afin que le \verb|\else| ou le \verb|\fi| demeurent hors de l'�valuation faite par le test.
\end{regle}

Ainsi, le test �\verb|\ifx a\fi|� devient �\verb|\ifx a|\boxtoken\relax\verb|\fi|� o� le \boxtoken\relax est un \idx\relax sp�cial ins�r� par \TeX{} et qui sera compar� avec �\verb|a|�. De m�me, le test �\verb|\ifnum1=2\else3\fi|� devient �\verb|\ifnum1=2|\boxtoken\relax\verb|\else3\fi|� o� le \idx\relax sp�cial interrompt la lecture du nombre 2.
\grandsaut

Voici comment d�finir une macro �\specialrelax dont le texte de remplacement est un \idx\relax sp�cial :

\centrecode-\edef\specialrelax{\ifnum1=1\fi}-

\noindent Ici, un \boxtoken\relax sera ins�r� avant le \verb|\fi| et comme le test est vrai, ce \boxtoken\relax sera tout ce qui reste dans la branche du test.

\showcode/\edef\specialrelax{\ifnum1=1\fi}��*\specialrelax�
\meaning\specialrelax�\idx*\meaning�/

Pourquoi dit-on \idx\relax \emph{sp�cial} et non pas \idx\relax tout court ? Les \idx\relax sp�ciaux ins�r�s par \TeX{} sont diff�rents des \idx\relax ordinaires lus dans le code source aux yeux de \TeX{} lui-m�me. En voici la preuve :

\showcode/\edef\specialrelax{\ifnum1=1\fi}% texte de remplacement = \relax sp�cial��*\specialrelax�
\edef\normalrelax{\relax}% texte de remplacement = \relax normal
\meaning\specialrelax\par�\idx*\meaning�
\meaning\normalrelax\par
Les 2 \string\relax{} sont \ifx\specialrelax\normalrelax identiques\else diff�rents\fi.�\idx*\string�*\specialrelax�/

Ils sont diff�rents car \boxtoken\relax n'est \emph{pas} une primitive. C'est un token interne d�fini dans le programme \texttt{tex} lui-m�me qui se donne l'apparence de \idx\relax mais qui est cod� en dur et qui n'est pas modifiable par l'utilisateur. Autant on pourrait vivre dangereusement et red�finir la primitive \idx\relax, autant il est impossible de red�finir \boxtoken\relax :

\errcode/\edef\specialrelax{\ifnum1=1\fi}��*\specialrelax�
\expandafter\def\specialrelax{foobar}% red�finition un \relax sp�cial��*\specialrelax�/{Missing control sequence inserted}%
\idx*[!sp�cial|)]\relax\idx*[|)]{test incomplet}

\section{Tests successifs}
\subsection{Programmation du test \texttt{\textbackslash ifnumcase}}�*\ifnumcase[|(]%
Nous avons vu le test \tidx{ifcase}\verb|<nombre>|, cousin de \tidx{ifnum}, qui permettait de d�cider que faire selon des valeurs enti�res du \verb|<nombre>|. L'inconv�nient est que ces valeurs doivent commencer � 0 et se suivre de 1 en 1. Cette contrainte rend ce test inutilisable si l'on souhaite tester si le \verb|<nombre>| est successivement �gal � des valeurs non cons�cutives et distantes les unes des autres. L'id�e est donc de cr�er un test qui d�cide que faire selon des valeurs enti�res pr�cis�es par l'utilisateur (par exemple $-5$, 14, $-16$, 20) et offrir une branche facultative �\elseif o� un code alternatif sera ex�cut� si aucune �galit� n'a �t� rencontr�e.

Nous allons nous fixer la syntaxe suivante :

\centrecode/\ifnumcase{<nombre>}%
       {<valeur 1>}{<code 1>}
       {<valeur 2>}{<code 2>}
       ...
       {<valeur n>}{<code n>}
\elseif
       <code alternatif>
\endif��*\endif�/

Le �\elseif et le \verb|<code alternatif>| qui le suit sont facultatifs.

De plus, nous allons nous imposer une contrainte : lorsqu'un \verb|<code>| est ex�cut�, il doit pouvoir acc�der aux tokens qui suivent le �\endif. Autrement dit, ce \verb|<code>| doit �tre ex�cut� � la toute fin du traitement, juste avant que la macro ne rende la main.

L'id�e directrice est de lire tout d'abord le \verb|<nombre>| puis de passer la main � une macro r�cursive qui va lire ensuite \emph{un seul} argument. Si cet argument est :

\begin{itemize}
       \item une \verb|<valeur k>|, lire le \verb|<code k>| et l'ex�cuter si le test est vrai apr�s avoir tout mang� jusqu'au �\endif. S'il est faux, recommencer;
       \item �\elseif, aucun test n'a �t� vrai et il faut ex�cuter le \verb|<code alternatif>| apr�s avoir tout mang� jusqu'au �\endif;
       \item �\endif, cela signifie la fin du processus et correspond au cas o� �\elseif n'est pas pr�sent et aucun test n'a �t� vrai.
\end{itemize}

Comme nous ne savons pas encore tester si un argument est une \verb|<valeur>| (c'est-�-dire un entier), nous allons d'abord tester si l'argument est �\elseif puis s'il est �\endif et si les deux tests pr�c�dents sont n�gatifs, nous consid�rerons que c'est un entier.

Afin d'�tre propre dans la programmation, l'ensemble du processus se d�roulera dans un groupe semi-simple. Il conviendra de le fermer au bon moment. Pour faciliter la comparaison avec \tidx{ifx}, les macros �\elseif et �\endif seront des \idx[|(]{quark}s locaux � ce groupe.

\begin{algo}
       \item ouvrir un groupe, lire le \verb|<nombre>|, d�finir les quarks \verb|\elseif| et \verb|\endif|;
       \item lire le premier argument $x$ qui suit ;
       \begin{algo}
               \item si $x={}$�\elseif, fermer le groupe et ex�cuter tout ce qui reste jusqu'� �\endif ;
               \item sinon
               \begin{itemize}
                       \item si $x={}$�\endif fermer le groupe;
                       \item sinon, cela signifie que $x$ est une \verb|<valeur>|
                       \begin{algo}%[label=(\roman*)]
                               \item si $x={}$\verb-<nombre>-, fermer le groupe, ex�cuter l'argument suivant apr�s voir tout supprim� tout jusqu'� �\endif ;
                               \item si $x\neq{}$\verb-<nombre>-, manger l'argument suivant et retourner en 2.
                       \end{algo}
               \end{itemize}
       \end{algo}
\end{algo}

Nous aurons besoin d'une macro auxiliaire r�cursive pour le point 2 ainsi que d'une macro auxiliaire qui s'occupe du point 2a que nous appellerons \verb|\idto@endif| :

\centrecode-\def\idto@endif#1\endif{#1}-�*\endif

\noindent et d'une autre pour le point 2bi) que nous appellerons \verb|\firstto@endif|. Elle sera charg�e de lire l'argument suivant (argument non d�limit� \verb|#1|) et de lire tout ce qui se trouve jusqu'au �\endif (qui sera un argument d�limit�). Son texte de remplacement sera le premier argument :

\centrecode-\def\firstto@endif#1#2\endif{#1}-�*\endif

Voici le code :

\showcode/\catcode`\@11
\def\ifnumcase#1{%��*\ifnumcase�
       \begingroup�\idx*\begingroup�
       \def\elseif{\elseif}\def\endif{\endif}% d�finir deux "quarks" locaux��*\elseif�*\endif�
       \def\nombre@{#1}% stocker le nombre � comparer dans \nombre@
       \ifnumcase@i% appeller la macro r�cursive
}

\def\ifnumcase@i#1{%
       \def\nxt@arg{#1}% stocker l'argument suivant
       \ifx\nxt@arg\elseif% si c'est \elseif��*\elseif�
               \def\next@todo{\endgroup\idto@endif}% fermer le groupe et aller � \idto@endif
       \else
               \ifx\nxt@arg\endif% si c'est \endif��*\endif�
                       \let\next@todo\endgroup% fermer le groupe
               \else
                       \ifnum\nombre@=\nxt@arg% s'il y a �galit�
                               \def\next@todo{\endgroup\firstto@endif}% fermer le groupe puis \firstto@endif
                       \else% sinon
                               \let\next@todo=\ifnumcase@ii% aller � \ifnumcase@ii
                       \fi
               \fi
       \fi
       \next@todo% ex�cuter l'action d�cid�e ci-dessus
}

\def\ifnumcase@ii#1{\ifnumcase@i}
\def\idto@endif#1\endif{#1}
\def\firstto@endif#1#2\endif{#1}
\catcode`\@12
\def\swaptwo#1#2{#2#1}��*\swaptwo�
\def\testenombre#1{%
       \ifnumcase{#1}
               {1}{C'est "un" et je prends le premier argument: \firstoftwo}��*\firstoftwo�
               {3}{J'ai vu un "trois" et je mange les deux arguments : \gobtwo}��*\gobtwo�
               {15}{L'argument est "15" et je prends le second argument : \secondoftwo}��*\secondoftwo�
       \elseif��*\elseif�
               ni 1, ni 3, ni 5 et j'inverse les deux arguments : \swaptwo��*\swaptwo�
       \endif��*\endif�
}
\testenombre{3}{foo}{bar}\par
\testenombre{16}{foo}{bar}\par
\testenombre{15}{foo}{bar}\par
\testenombre{1}{foo}{bar}/

Pour mettre en �vidence que chaque \verb|<code>| a acc�s � ce qui se trouve imm�diatement apr�s le �\endif, les macros �\firstoftwo, �\secondoftwo sont appel�es � la fin des \verb|<code>| pour qu'elles agissent sur les arguments qui suivent le �\endif. Une nouvelle macro �\swaptwo qui inverse l'ordre des deux arguments suivants est �galement utilis�e.

\begin{exercice}
En l'�tat, la macro �\ifnumcase n'est pas purement d�veloppable, c'est-�-dire qu'on ne peut pas la mettre dans un \idx\edef. Comment pourrait-on la modifier pour qu'elle le devienne (� condition bien s�r que les \verb|<code>| le soient) ?
\solution
Les primitives non d�veloppables doivent �tre supprim�es : \idx\begingroup, \idx\endgroup, \idx\def et \idx\let. Il n'y aura plus de groupe semi-simple et les \idx{quark}s seront donc d�finis de fa�on globale, � l'ext�rieur de la macro �\ifnumcase.

Dans les branches des tests de \verb|\ifnumcase@i|, nous pouvons facilement nous passer de la macro \verb|\next@todo| � condition de recourir aux macros �\firstoftwo et �\secondoftwo qui rejettent hors des branches les codes ex�cut�s selon l'issue du test. En revanche, il est plus difficile de se passer de \verb|\nombre@| qui a stock� le \verb|<nombre>| dans la macro chapeau. La seule alternative est de passer le \verb|<nombre>| comme argument suppl�mentaire � la macro r�cursive.

Le code tend � se simplifier : l'essentiel est d�sormais fait par la macro r�cursive �\ifnumcase qui � chaque fois, va lire le m�me premier argument (le \verb|<nombre>|) ainsi qu'un second argument qui devra �tre test� pour d�cider que faire. Dans le cas o� ce second argument est une \verb|<valeur>|, il faudra aller lire le \verb|<code>| correspondant, soit pour l'ex�cuter, soit pour le manger avant de repartir pour un tour.

\showcode/\catcode`\@11
\def\endif{\endif}\def\elseif{\elseif}% d�finit les quarks��*\elseif�*\endif�

\def\ifnumcase#1#2{% #1=<nombre>   #2=prochain argument
       \ifx\elseif#2% si #2 est \elseif��*\elseif�
       \expandafter\firstoftwo\else\expandafter\secondoftwo\fi��*\firstoftwo�*\secondoftwo�
               \idto@endif% aller � \idto@endif, sinon :
               {\ifx\endif#2% si #2 est \endif��*\endif�
               \expandafter\firstoftwo\else\expandafter\secondoftwo\fi��*\secondoftwo�
                       {}% ne rien faire. Sinon #2 est une <valeur i>:
                       {\ifnum#1=#2 % s'il y a �galit� entre <nombre> et <valeur i>
                       \expandafter\firstoftwo\else\expandafter\secondoftwo\fi��*\secondoftwo�
                               \firstto@endif% aller � \firstto@endif
                               {\ifnumcase@i{#1}}% sinon aller � \ifnumcase@i
                       }%
               }%
}

\def\ifnumcase@i#1#2{% #1=<nombre>  #2=<code i> � suivre qui est mang�
       \ifnumcase{#1}% retourner � \ifnumcase en transmettant #1
}

\def\idto@endif#1\endif{#1}
\def\firstto@endif#1#2\endif{#1}
\catcode`\@12
\def\swaptwo#1#2{#2#1}��*\swaptwo�
\def\testenombre#1{%
       \ifnumcase{#1}
               {1}{C'est "un" et je prends le premier argument: \firstoftwo}��*\firstoftwo�
               {3}{J'ai vu un "trois" et je mange les deux arguments : \gobtwo}��*\gobtwo�
               {15}{L'argument est "15" et je prends le second argument : \secondoftwo}��*\secondoftwo�
       \elseif��*\elseif�
               ni 1, ni 3, ni 5 et j'inverse les deux arguments : \swaptwo��*\swaptwo�
       \endif��*\endif�
}
\testenombre{3}{foo}{bar}\par
\testenombre{16}{foo}{bar}\par
\testenombre{15}{foo}{bar}\par
\edef\macro{\testenombre{1}{foo}{bar}}\meaning\macro/
\idx*[|)]{quark}�*\ifnumcase[|)]\end{exercice}

\subsection{Programmation du test \texttt{\textbackslash ifxcase}}�*\ifxcase[|(]%
Il ne nous reste plus qu'� faire la m�me chose avec le test \tidx{ifx} en programmant une macro \verb|\ifxcase| dont voici la syntaxe :

\centrecode/\ifxcase <token>
       <token 1>{<code 1>}
       <token 2>{<code 2>}
       ...
       <token n>{<code n>}
\elseif%��*\elseif�
       <code alternatif>
\endif��*\endif�/

\noindent qui compare successivement \verb|<token>| avec \verb|<token 1>|, \verb|<token 2>|, etc, o� les comparaisons sont faites au sens de \tidx{ifx}. Si un des tests est positif, le \verb|<code i>| correspondant sera ex�cut� et sinon, ce qui se trouve apr�s la macro facultative �\elseif le sera.

Il n'y a rien de bien difficile, il suffit de recopier le code de �\ifnumcase en rempla�ant le test \tidx{ifnum} par \tidx{ifx}: \label{ifxcase}

\showcode/\catcode`\@11
\def\endif{\endif}\def\elseif{\elseif}%��*\elseif�*\endif�
\def\ifxcase#1#2{% #1=<token>   #2=prochain argument
       \ifx\elseif#2% si #2 est \elseif��*\elseif�
       \expandafter\firstoftwo\else\expandafter\secondoftwo\fi��*\firstoftwo�*\secondoftwo�
               \idto@endif% aller � \idto@endif, sinon :
               {\ifx\endif#2% si #2 est \endif��*\endif�
               \expandafter\firstoftwo\else\expandafter\secondoftwo\fi��*\secondoftwo�
                       {}% ne rien faire. Sinon #2 est un <token i>:
                       {\ifx#1#2% s'il y a �galit� entre <token> et <token i>
                       \expandafter\firstoftwo\else\expandafter\secondoftwo\fi��*\secondoftwo�
                               \firstto@endif% aller � \firstto@endif
                               {\ifxcase@i{#1}}% sinon aller � \ifnumcase@i
                       }%
               }%
}
\def\ifxcase@i#1#2{% #1=<token>  #2=<code i> � suivre (qui est mang�)
       \ifxcase{#1}% retourner � \ifxcase en transmettant #1
}
\def\idto@endif#1\endif{#1}
\def\firstto@endif#1#2\endif{#1}
\catcode`\@12
\def\testtoken#1{%��*\testtoken�
       \ifxcase{#1}
               a{Le token est "a"}
               +{J'ai vu un "+"}
               \relax{L'argument est "\string\relax"}�\idx*\string�
       \elseif��*\elseif�
               Tous les tests sont n�gatifs%
       \endif��*\endif�
}
1) \testtoken a\par
2) \let\foo=a\testtoken\foo\par
3) \testtoken+\par
4) \testtoken\relax\par
5) \edef\foo{\testtoken\relax}\meaning\foo\par�\idx*[|etc]\meaning\forbidindex\meaning�
6) \edef\foo{\testtoken W}\meaning\foo��*\testtoken�/

On constate aux cas \nos1 et 2 que le test est positif aussi bien lorsque le \verb|<token>| est un �\verb|a|� explicite que lorsqu'il est une macro \idx\let-�gale au caract�re �\verb|a|�.�*\ifxcase[|)]%

\chapter{Une boucle � loop repeat �}
\section{Impl�mentation de plain-\TeX}
Plain-\TeX{} d�finit lui-m�me sa boucle � \idx\loop\ldots\idx\repeat � dont voici l'impl�mentation telle qu'elle a �t� �crite par \idx*{Knuth Donald}D.~\textsc{Knuth} :

\centrecode-\def\loop#1\repeat{\def\body{#1}\iterate}�\idx*\iterate\idx*\loop�
\def\iterate{\body \let\next\iterate \else\let\next\relax\fi \next}
\let\repeat=\fi-

Il est clair que la macro \idx\loop est � argument d�limit� (le d�limiteur est \idx\repeat) et stocke dans la macro \idx\body tout ce qui se trouve entre \idx\loop et \idx\repeat (que l'on appelle � corps de la boucle�) avant d'appeler la macro \idx\iterate. On remarque �galement qu'aucune macro n'est d�clar�e \idx\long et donc il faudra proscrire la primitive \idx[|etc]\par\forbidindex\par{} entre \idx\loop et \idx\repeat. Ensuite, l'id�e est que ce qui se trouve entre \idx\loop et \idx\repeat, stock� dans \idx\body, \emph{doit} contenir un test. Ce test, s'il est positif, autorisera la boucle ex�cuter une it�ration de plus tandis que s'il est n�gatif, il constitue la \emph{condition d'arr�t} de la boucle qui lui commande de s'arr�ter. Cela suppose que le corps de la boucle modifie un param�tre pris en compte par le test afin que ce dernier devienne � un moment n�gatif pour permettre la sortie de la boucle et �viter ainsi une boucle infinie.

Le m�canisme est assez facile � saisir : ce test sera ex�cut� lorsque \idx\iterate puis \idx\body seront d�velopp�s. Si ce test est positif, \verb|\next| est rendue \idx\let-�gale � \idx\iterate et sinon, elle est rendue \idx\let-�gale � \idx[|etc]\relax\forbidindex\relax. Cette macro \verb|\next| est ensuite appel�e apr�s �tre sorti du test, ce qui rend la r�cursivit� terminale\idx*{r�cursivit�!terminale}.

La structure de la boucle est donc la suivante :

\centrecode-\loop
       <code a>
       <test>
       <code b>
\repeat-

\noindent o� les \verb|<code a>| et \verb|<code b>| sont facultatifs, c'est-�-dire que l'un ou l'autre peuvent �tre r�duit � 0 token. Il est en revanche important de comprendre que \verb|<code a>| est toujours ex�cut� au moins une fois puisqu'il vient avant le test.

De par sa construction, il est �galement important de remarquer que ce qui se trouve entre \idx\loop et \idx\repeat ne doit pas contenir un test accompagn� d'un \verb|\else| puisqu'un \verb|\else| est d�j� �crit en dur dans la macro \idx\iterate. Si l'utilisateur �crivait un \verb|\else| par m�garde, cela provoquerait une erreur de type �\verb|extra \else|� lorsque \TeX{} atteindrait le second \verb|\else|. Malgr� cette petite contrainte, cette structure est tr�s souple du fait que le test peut se trouver o� l'on veut entre \idx\loop et \idx\repeat.

Enfin, on constate � la derni�re ligne que \idx\repeat est rendu \idx\let-�gal � \verb|\fi| ce qui a pour cons�quence que \idx\repeat sera vu par \TeX{} comme un \verb|\fi| et donc pris en compte lors du comptage interne de \TeX{} des tests, \verb|\else| et des \verb|\fi|. En d'autres termes, le \idx\repeat sera bien appari� avec le \verb|<test>| se trouvant entre \idx\loop et \idx\repeat et par cons�quent, la boucle peut �tre mise dans les branches d'un test sans provoquer de mauvais appariements entre les tests et les \verb|\fi|. Une structure de ce type est donc tout � fait envisageable :

\centrecode-<test>
       <code 1>
       \loop
               ...
       \repeat
       <code 2>
\else
       <code 3>
       \loop
               ...
       \repeat
       <code 4>
\fi-

Voici � titre d'exemple comment on peut programmer la macro �\compte vue dans un exercice du chapitre~\ref{compte} :

\showcode/\newcount\xx % d�finit un compteur utilis� dans la boucle�\idx*\newcount�
\def\compte#1{%��*\compte�
       \xx=0 % initialise le compteur
       \loop% d�but de la boucle�\idx*\loop�
               \advance\xx1 % incr�mente le compteur�\idx*\advance�
               \ifnum\xx<#1 % s'il est inf�rieur � la borne
                 \number\xx , % affiche le nombre et la virgule�\idx*[|etc]\number\forbidindex\number�
       \repeat% et recommence�\idx*\repeat�
       \ifnum#1>0 \number\xx\relax\fi% si le nombre #1 est >0, afficher le dernier nombre
       }
a) \compte{1}.\qquad b) \compte{-3}.\qquad c) \compte{7}.��*\compte�/

\section{Impl�mentation de \LaTeX}
Le \idx[!\LaTeX]{format}\LaTeX{} red�finit la boucle \idx\loop\ldots\idx\repeat de cette fa�on :

\centrecode-\long\def\loop#1\repeat{%�\idx*\long\idx*\loop\idx*\repeat�
 \def\iterate{#1\relax\expandafter\iterate\fi}%�\idx*\iterate�
 \iterate
 \let\iterate\relax}�\idx*\iterate�
\let\repeat=\fi-

La macro \idx\loop est d�clar�e \idx\long et l'on fait l'�conomie de la macro \idx\body en d�clarant \idx\iterate comme une � sous-macro � de \idx\loop de telle sorte que l'argument \verb|#1| lui soit accessible. En consid�rant que \verb|#1| contient un test, on voit clairement que ce test peut �tre accompagn� d'un \verb|\else| puisque le code de la macro \idx\iterate ne comporte pas cette primitive mais seulement un \verb|\fi|. Le plus simple est de faire fonctionner la boucle dans les cas o� son corps contient un \verb|\else| ou pas :\medbreak

\noindent
\begin{minipage}[t]{.5\linewidth}
\footnotesize
\hfill Sans \verb|\else|\hfill\null
\centrecode-\loop
       <code a>
       <test>
               <code b>
\repeat-
\end{minipage}%
\begin{minipage}[t]{.5\linewidth}
\footnotesize
\hfill Avec \verb|\else|\hfill\null
\centrecode-\loop
       <code a>
       <test>
               <code b>
       \else
               <code c>
\repeat-
\end{minipage}\medbreak

Voil� ce qui est stock� dans la macro \idx\iterate dans chaque cas :\medbreak

\noindent
\begin{minipage}[t]{.5\linewidth}
\footnotesize
\hfill Sans \verb|\else|\hfill\null
\centrecode-<code a>
<test>
       <code b>\relax
       \expandafter\iterate
\fi-
\end{minipage}%
\begin{minipage}[t]{.5\linewidth}
\footnotesize
\hfill Avec \verb|\else|\hfill\null
\centrecode-<code a>
<test>
       <code b>
\else
       <code c>\relax
       \expandafter\iterate
\fi-
\end{minipage}\medbreak

Il est maintenant facile de constater que si le corps de la boucle contient un \verb|\else|, c'est la branche du test n�gatif (apr�s le \verb|\else|) qui maintiendra la r�cursivit�. En revanche, s'il n'y a pas de \verb|\else|, c'est la branche du test positif qui la maintient. Autrement dit, la condition d'arr�t est un test \emph{n�gatif} s'il n'y a pas de \verb|\else| alors que c'est un test \emph{positif} s'il y en a.

Malgr� ce petit manque de coh�rence, on peut dire que l'impl�mentation \LaTeX{} est sup�rieure � celle de plain-\TeX{} puisque la souplesse de pouvoir mettre de \verb|\else| dans la boucle rend parfois service, sans compter que l'on peut �galement faire appel � \tidx{unless} pour �changer les branches du test.

\section{Imbrications de boucles}
Malgr� leur c�t� pratique, ni l'impl�mentation \TeX{} ni celle de \LaTeX{} ne permettent l'imbrication de boucles \idx\loop\ldots\idx\repeat, principalement � cause de deux choses :

\begin{itemize}
       \item si deux boucles �taient imbriqu�es, le \idx\repeat de la boucle int�rieure serait pris comme fin de la boucle ext�rieure puisqu'avec les arguments d�limit�s, la premi�re occurrence du d�limiteur est prise en compte ;
       \item la macro \idx\iterate serait red�finie par la boucle int�rieure.
\end{itemize}

Avec la syntaxe actuelle, aucune impl�mentation facile � programmer et n'utilisant pas de groupe permet d'imbriquer des boucles \idx\loop \idx\repeat n'est faisable. La difficult� est de trouver ce qui se trouve entre un \idx\loop et son \idx\repeat appari� ! Nous allons donc tenter de b�tir une boucle �\xloop\verb|...|�\xrepeat, fonctionnant de la m�me fa�on que \verb|\loop...\repeat| sauf que l'imbrication des boucles sera possible.

Pour commencer, nous allons nous attacher � collecter le code compris entre un �\xloop et son �\xrepeat appari�. Ce code sera stock� dans la macro \verb|\xiterate| et simplement \emph{affich�}  :

\begin{algo}
       \item d�finir un compteur \verb|\cnt@repeat| qui comptabilisera les occurrences de �\xrepeat rencontr�es, et l'initialiser � 0. Initialiser \verb|\xiterate| � vide;
       \item ajouter � \verb|\xiterate| tout le code qui se trouve jusqu'au prochain �\xrepeat;
       \item stocker dans \verb|\cnt@loop| le nombre de fois que �\xloop est contenu dans le texte de remplacement de \verb|\xiterate|;
       \item tester si \verb|\cnt@loop|${}={}$\verb|\cnt@repeat|;
       \begin{algo}
               \item si le test est positif, afficher le texte de remplacement de \verb|\xiterate| � l'aide \idx\detokenize;
               \item sinon, incr�menter \verb|\cnt@repeat|, ajouter �\xrepeat � \verb|\xiterate| et retourner en 2.
       \end{algo}
\end{algo}

Voici un code \TeX{} qui transcrit cet algorithme, o� nous nous servons des macros �\addtomacro et �\ifin vues pr�c�demment. Nous utiliserons aussi la macro \verb|\cnttimestocs| vue dans la solution � la page~\pageref{cnttimes} :

\showcode/\catcode`\@11
\newcount\cnt@repeat % d�finit le compteur de \xrepeat�\idx*\newcount�

\def\xloop{%��*\xloop�
       \def\xiterate{}% initialiser \xiterate � vide
       \cnt@repeat\z@% initialiser le compteur de \xrepeat�\idx*\z@�
       \xloop@i% aller � la macro r�cursive
}

\long\def\xloop@i#1\xrepeat{%�\idx*\long �*\xrepeat�
       \addtomacro\xiterate{#1}% ajoute ce qui est avant le premier \xrepeat��*\addtomacro�
       \exparg\cnttimestocs{\xiterate}\xloop\cnt@loop
       % combien de \xloop dans \xiterate��*\cnttimestocs�
       \ifnum\cnt@loop=\cnt@repeat\relax
               \expandafter\firstoftwo\else\expandafter\secondoftwo��*\firstoftwo�*\secondoftwo�
       \fi
               {% autant que de \xrepeat -> \detokenize pour afficher
               "\detokenize\expandafter{\xiterate}"%
               }
               {\addtomacro\xiterate\xrepeat% sinon, ajouter ce \xrepeat
               \advance\cnt@repeat by 1% incr�menter le compteutr de \xrepeat�\idx*\advance�
               \xloop@i% et chercher le prochain \xrepeat
               }%
}
\let\xrepeat\fi
\catcode`\@12
\xloop a\xloop b\xloop 12\xrepeat c\xrepeat \xloop X\xrepeat\xrepeat��*\xloop�*\xrepeat�/

Cela fonctionne bien : tout ce qui se trouve entre le premier �\xloop et son �\xrepeat appari� (qui est le dernier ici) est bien affich�. Maintenant, au lieu de simplement d�tok�nizer le texte de remplacement de \verb|\xiterate|, nous allons mimer avec cette macro ce que fait l'impl�mentation \LaTeX{}. De plus, au lieu d'�crire \verb|\xiterate|, il faudra �crire partout dans le code \verb|\xiterate@<n>| de telle sorte que les imbrications de boucles ne red�finissent pas cette macro et aient chacune la leur. Le nombre \verb|<n>| est le compteur d'imbrications stock� dans le compteur \verb|\cnt@nested|. Celui-ci est initialis� � 0 en dehors de toute macro, incr�ment� � chaque fois que �\xloop est rencontr� et d�cr�ment� lors de la sortie de boucle.

Bien entendu, pour former la macro \verb|\xiterate@<n>|, il va falloir faire appel � la paire \idx\csname\ldots\verb|\endcsname| et donc, alourdir sensiblement le code :

\showcode/\catcode`\@11
\newcount\cnt@repeat�\idx*\newcount�
\newcount\cnt@nested
\cnt@nested=0 % compteur d'imbrications
\def\xloop{%��*\xloop�
       \global\advance\cnt@nested by 1 % augmente le compteur d'imbrications�\idx*\global\idx*\advance�
       \expandafter\def\csname xiterate@\number\cnt@nested\endcsname{}%
       \cnt@repeat\z@% initialise le compteur de \xrepeat � 0�\idx*\z@�
       \xloop@i% aller � la macro \xloop@i
}
\long\def\xloop@i#1\xrepeat{%��*\xrepeat\idx*\long�
       \expandafter\addtomacro\csname xiterate@\number\cnt@nested\endcsname{#1}%�\defline\eee�*\addtomacro�
       \expandafter\expandafter\expandafter\cnttimestocs\expandafter\expandafter\expandafter��*\cnttimestocs�
               {\csname xiterate@\number\cnt@nested\endcsname}\xloop\cnt@loop�\idx*\csname\idx*\endcsname�
       \ifnum\cnt@loop=\cnt@repeat\relax
               \expandafter\firstoftwo\else\expandafter\secondoftwo��*\firstoftwo�*\secondoftwo�
       \fi
               {\expandafter\eaddtomacro\csname xiterate@\number\cnt@nested\expandafter\endcsname�\defline\bbb�*\eaddtomacro�
                       {\expandafter\expandafter\csname xiterate@\number\cnt@nested\endcsname\fi}%
               %\expandafter\show\csname xiterate@\number\cnt@nested\endcsname�\defline\aaa\idx*\show�
               \csname xiterate@\number\cnt@nested\endcsname�\defline\ddd�
               \letname{xiterate@\number\cnt@nested}\relax��*\letname�
               \global\advance\cnt@nested by -1�\defline\ccc\idx*\global\idx*\advance�
               }
               {\expandafter\addtomacro\csname xiterate@\number\cnt@nested\endcsname\xrepeat��*\addtomacro�*\xrepeat�
               \advance\cnt@repeat by 1 �\idx*\advance�
               \xloop@i
               }%
}%
\let\xrepeat\fi��*\xrepeat�
\catcode`\@12

\newcount\cntxx \cntxx=1 % compteur des lignes
\newcount\cntyy�\idx*\newcount�
\xloop��*\xloop�
       \cntyy=1 % compteur des colonnes
       \xloop��*\xloop�
               (\number\cntxx,\number\cntyy)% affiche "(ligne,colonne)"
               \ifnum\cntyy<5 % tant que colonne<5
               \advance\cntyy1 % incr�mente colonne
               , % <- affiche ", "
       \xrepeat% et recommence
       \ifnum\cntxx<3 % tant que ligne<3
       \advance\cntxx1 % incr�mente ligne
       \par % va � la ligne
\xrepeat% et recommence��*\xrepeat�/

L'utilisation de \verb|\csname...\endcsname| rend la lecture du code bien plus difficile puisqu'elle implique le d�veloppement d'un pont d'\idx\expandafter pour faire naitre une macro puis pour acc�der � son texte de remplacement d'une macro (lignes \nos\eee{} � \number\eee+3\relax). Malgr� cela, intrins�quement, le code est identique � celui vu pr�c�demment. La seule diff�rence se trouve entre les lignes \nos\bbb{} � \no\ccc. En effet, aux lignes \nos\bbb{}-\number\numexpr\bbb+1\relax{}, au lieu de d�tok�nizer la macro \verb|\xiterate@<n>| pour simplement l'afficher comme on le faisait en analyse pr�alable, on ajoute au texte de remplacement de cette macro �\idx\expandafter� suivi du nom de la macro, c'est-�-dire \verb|\xiterate@<n>| que l'on fait suivre d'un \verb|\fi|. Ainsi, le texte de remplacement de \verb|\xiterate@<n>| est finalement :

\centrecode-<ce qui est entre \xloop et \xrepeat> \expandafter\xiterate@<n> \fi-

On peut d'ailleurs prendre connaissance du texte de remplacement de la macro \verb|\xiterate@<n>| en d�-commentant la ligne \no\aaa{} pour laisser � la primitive \idx\show l'�crire dans le \idx[!log]{fichier} \verb|log|. Pour \verb|\xiterate@1|, on obtient :

\centrecode|\xiterate@1=macro:->
\cntyy =1
\xloop��*\xloop�
       (\number \cntxx ,\number \cntyy )
       \ifnum \cntyy <5 ,
       \advance \cntyy 1
\xrepeat��*\xrepeat�
\ifnum \cntxx <3
       \advance \cntxx 1
       \par
       \expandafter\xiterate@1
\fi.|

\noindent et pour \verb|\xiterate@2| :

\centrecode|\xiterate@2=macro:->
(\number \cntxx ,\number \cntyy )
\ifnum \cntyy <5 ,
\advance \cntyy 1
       \expandafter\xiterate@2
\fi.|

\noindent C'est exactement ce que fait l'impl�mentation \LaTeX{} de la boucle \idx\loop\ldots\idx\repeat avec la macro \idx\iterate. En poursuivant le parall�le avec la boucle \LaTeX{}, il suffit ensuite de lancer la macro \verb|\xiterate@<n>| � la ligne \no\ddd{} et une fois la boucle termin�e, on rend \verb|\iterate@<n>| \idx\let-�gale � \idx\relax � la ligne \no\number\numexpr\ddd+1\relax. Le tout se termine avec la d�cr�mentation du compteur d'imbrication � la ligne \no\ccc.

\chapter{Une boucle � foreach in �}\label{doforeach}
\section{Une premi�re approche}
Nous allons construire une boucle o� une � variable � --~qui sera comme pr�c�demment une s�quence de contr�le~-- prendra successivement toutes les valeurs d'une liste de valeurs, pas n�cessairement num�riques, s�par�es par des virgules et � chaque it�ration, un code sera ex�cut�. La syntaxe de cette boucle, initi�e par la macro �\doforeach[|(], sera\footnote{La commande \texttt{\string\foreach} est d�finie par le \idx[!pgf]{package} �\texttt{pgf}� et pour �viter tout conflit, il vaut donc mieux choisir un autre nom.} :

\centrecode-\doforeach\<macro>\in{<valeur 1>,<valeur 2>,...,<valeur n>}{<code>}-

\noindent o� bien entendu, le \verb|<code>| peut contenir la \verb|\<macro>|.

La m�thode, relativement simple, va �tre de lire toutes les valeurs une premi�re fois, y ajouter � la fin une valeur reconnaissable (un \idx{quark}) et par la suite, lire les valeurs une par une jusqu'� ce qu'apparaisse le \idx{quark}. Nous mettons ici en \oe uvre la m�thode recommand�e pour lire une s�rie d'arguments (voir page~\pageref{lire.arguments}) :

\begin{algo}
       \item lire la liste des valeurs et lui ajouter �\verb-,\end@foreach,-�, o� \verb-\end@foreach- est un \idx{quark}.

       Sauvegarder le \verb|<code>| dans une macro (que nous appelons \verb|\loop@code|);
       \item lire la valeur qui se trouve avant la virgule et l'assigner � \verb|\<macro>| ,
       \item si \verb|\<macro>|=\verb-\end@foreach-, finir le processus ;
       \item sinon ex�cuter le \verb|<code>| et retourner en 2.
\end{algo}

Le point 1 sera d�volu � une macro chapeau charg�e de faire les assignations pr�alables. Les autres points seront contenus dans une macro r�cursive � argument d�limit�. Choisissons d'externaliser la macro r�cursive (c'est-�-dire de la d�finir en dehors du texte de remplacement de la macro chapeau). Assurons-nous que la macro r�cursive peut acc�der � tous les arguments de la macro chapeau. Aucun probl�me pour la liste des valeurs qu'elle lira comme argument au fur et � mesure. Le \verb|<code>| ne pose pas de probl�me puisqu'il est sauvegard� dans \verb|\loop@code|. La variable \verb|\<macro>| n'�tant pas sauvegard�e, prenons comme solution de la transmettre comme argument � la macro r�cursive : cette macro (qui n'est qu'un seul token) viendra comme premier argument non d�limit�, avant la liste des valeurs.

\showcode/\catcode`\@11
\def\end@foreach{\end@foreach}% d�finit un quark�\idx*{quark}�
\long\def\doforeach#1\in#2#3{%�\idx*\long�
       \def\loop@code{#3}% assigne le <code> � \loop@code
       % appel � \doforeach@i : mettre la macro #1 en premier, puis la liste de valeurs #2
       \doforeach@i#1#2,\end@foreach,% ajouter � la fin ",\end@foreach,"
       % une fois les boucles finies, neutraliser les macros d�j� d�finies
       \let#1\relax \let\loop@code\relax
}

\long\def\doforeach@i#1#2,{% #1=\<macro>  #2=valeur courante�\defline\aaa\idx*\long�
       \def#1{#2}% stocke la valeur en cours dans la \<macro>
       \unless\ifx\end@foreach#1% si \end@foreach n'est pas atteint
               \antefi% am�ne le \fi ici��*\antefi�
               \loop@code% ex�cute le code
               \doforeach@i#1% et recommencer
       \fi
}
\catcode`@12
\doforeach\x\in{a,bcd,{efg},hi}{\meaning\x.\par}/

La ligne \no\aaa{} montre que la macro \verb|\doforeach@i| admet comme argument \emph{non d�limit�} \verb|#1| alors que la valeur en cours est l'argument \verb|#2| d�limit� par la virgule. L'inconv�nient, li� � la lecture d'argument, est que si une \verb|<valeur>| est constitu�e d'un texte entre accolades, ce texte est d�pouill� de ses accolades et assign� � la variable. Si l'on souhaitait �viter cet �cueil, il faudrait mettre un token (par exemple un \idx\relax) avant chaque \verb|<valeur>| et faire en sorte de manger ce \idx\relax avec \verb|\gobone| avant d'assigner la \verb|<valeur>| � la variable. Par souci de simplicit�, cette man\oe uvre ne sera pas programm�e.

\begin{exercice}
On pourrait vouloir modifier le s�parateur de liste (qui est la virgule par d�faut) pour mettre des nombres d�cimaux dans la liste d'arguments, par exemple.

Cr�er une macro �\defseplist dont l'argument est le s�parateur voulu et modifier le code vu ci-dessus pour que la macro �\doforeach tienne compte du s�parateur ainsi d�fini.
\solution
L'id�e est de faire de �\defseplist\verb|<s�parateur>| une macro �enveloppante� qui va d�finir, � chaque fois qu'elle sera appel�e, les deux macros �\doforeach et \verb|\doforeach@i|, toutes les deux d�pendantes de l'argument \verb|#1| de �\defseplist. Dans le code d�j� vu, la virgule va �tre replac�e par \verb|#1| et les autres �\verb|#|� qui s'appliquent aux arguments de �\doforeach et \verb|\doforeach@i| vont �tre doubl�s pour tenir compte de l'imbrication des macros :

\showcode/\catcode`\@11
\def\end@foreach{\end@foreach}
\def\defseplist#1{%��*\defseplist�
       \long\def\doforeach##1\in##2##3{%�\idx*\long�
               \def\loop@code{##3}% assigne le <code> � \loop@code
               \doforeach@i##1##2#1\end@foreach#1% ajouter ",\end@foreach," et aller � \doforeach@i
               % apr�s �tre sorti des boucles, neutraliser les macros d�j� d�finies
               \let\loop@code\relax \let##1\relax
       }%
       \long\def\doforeach@i##1##2#1{%�\idx*\long�
               \def##1{##2}% stocke la valeur en cours dans la \<macro>
               \unless\ifx\end@foreach##1% si la fin n'est pas atteinte�\tidx*{unless}�
                       \antefi% am�ne le \fi ici��*\antefi�
                       \loop@code% ex�cute le code
                       \doforeach@i##1% et recommencer
               \fi
       }%
}
\defseplist{,}% d�finit les macros avec le s�parateur par d�faut��*\deseplist�
\catcode`@12

\doforeach\x\in{a,bcd,efg}{Argument courant : "\x".\par}\medbreak�\idx*\medbreak�

\defseplist{--}% s�parateur "--"��*\deseplist�
\doforeach\nn\in{4,19--0,5--8,575}{Nombre lu : "\nn"\par}/
\end{exercice}

\section{Rendre possible l'imbrication}
Il nous reste � rendre possible l'imbrication de boucles �\doforeach et pour cela, comme pr�c�demment avec �\for et �\xloop, nous allons d�finir un compteur qui sera charg� de compter le niveau d'imbrication et qui fera partie du nom de la macro charg�e de stocker le \verb|<code>|. Nous prendrons �\verb|\loop@code@<n>|� :

\showcode/\catcode`\@11
\newcount\cnt@nest \cnt@nest=0 % d�finit et initialise le compteur d'imbrication�\idx*\newcount�
\def\end@foreach{\end@foreach}

\def\defseplist#1{%��*\deseplist�
       \long\def\doforeach##1\in##2##3{%�\idx*\long�
               \global\advance\cnt@nest1 % entr�e de boucle : incr�menter le compteur d'imbrication�\idx*\global�
               \defname{loop@code@\number\cnt@nest}{##3}% assigne le <code> � \loop@code@<n>��*\defname�
               \doforeach@i##1##2#1\end@foreach#1% ajouter ",\end@foreach," et aller � \doforeach@i
               % une fois fini :
               \let##1\empty% dans ce cas, neutraliser les macros d�j� d�finies�\idx*\empty�
               \letname{loop@code@\number\cnt@nest}\empty%��*\letname�
               \global\advance\cnt@nest-1 %sortie de boucle : d�cr�menter le compteur d'imbrication�\idx*\global\idx*\advance�
       }%
       \long\def\doforeach@i##1##2#1{%�\idx*\long�
               \def##1{##2}% stocke la valeur en cours dans la \<macro>
               \unless\ifx\end@foreach##1% tant que la fin n'est pas atteinte�\tidx*{unless}�
                       \antefi% am�ne le \fi ici��*\antefi�
                       \csname loop@code@\number\cnt@nest\endcsname% ex�cute le code�\defline\aaa�
                       \doforeach@i##1% et recommencer
               \fi
       }%
}
\catcode`@12
\defseplist{,}��*\deseplist�

\doforeach\xxx\in{1,2,3}{%
       Ligne \xxx{} : \doforeach\yyy\in{a,b,c,d,e}{(\xxx,\yyy)}.\par
}/

Profitons �galement de la simplicit� relative de ce code pour impl�menter une fonctionnalit� qui pourrait �tre d'un grand secours. Si la � variable � est d�j� d�finie lorsque la boucle est rencontr�e, il serait judicieux de la sauvegarder pour la restaurer une fois la boucle termin�e. Imaginons en effet qu'un utilisateur imprudent --~ou inconscient~-- nomme sa variable \idx\par par analogie avec le mot � param�tre � et construise une boucle de cette fa�on :

\centrecode-\doforeach\par\in{a,b,c,y,z}{$\par_i$}-

La primitive \idx\par serait silencieusement red�finie � l'entr�e de la boucle, pour �tre rendue \idx\let-�gale � \idx\relax � la fin ce qui aurait pour effet de rendre \TeX{} incapable de former un paragraphe. On imagine les d�g�ts, d'autant plus incompr�hensibles que le tout se passe silencieusement. Il nous faut donc tester si la variable existe au d�but de la boucle et si tel est le cas, la sauvegarder avec \idx\let pour la restaurer � la fin du processus.

Il existe un test \tidx{ifdefined}\verb|\<commande>| de \idx\eTeX qui est vrai si la \verb|\<commande>| est d�finie et faux sinon. Ce test ne modifie pas la table de hashage\footnote{Les tests \texttt{\textbackslash @ifundefined\{\codeelement{nom}\}} et \texttt{\textbackslash @ifdefinable\textbackslash\codeelement{nom}} de \LaTeX{} forment la s�quence de contr�le \texttt{\textbackslash\codeelement{nom}} � l'aide de \texttt{\textbackslash csname} et testent si elle est �gale � \texttt{\textbackslash relax} auquel cas, la s�quence de contr�le est consid�r�e non d�finie. Cette m�thode pr�sente deux gros inconv�nients :
\begin{itemize}
       \item toute macro existante et \texttt{\textbackslash let}-�gale � \texttt{\textbackslash relax} est consid�r�e par ces tests comme �tant non d�finie;
       \item par l'utilisation de \texttt{\textbackslash csname}, une macro non d�finie devient d�finie et \texttt{\textbackslash let}-�gale � \texttt{\textbackslash relax}. Un autre d�g�t collat�ral est que la table de hashage est modifi�e puisqu'une nouvelle macro est cr��e.
\end{itemize}}. Il existe aussi un test de \idx\eTeX un peu similaire \tidx{ifcsname}\verb|<nom d'une commande>|\idx\endcsname, qui forme la \verb|<commande>| comme le ferait \idx\csname puis teste si elle existe, sans modifier la table de hashage.

La m�thode sera ici de mettre � profit \tidx{ifdefined} pour tester si la variable existe et la sauvegarder dans \verb|\saved@var@<n>| si le test est positif. � la sortie de la boucle, il suffira de faire la man\oe uvre inverse pour restaurer la variable soit � \idx\relax, soit � ce qu'elle �tait avant si elle existait auparavant.

Dans le code ci-dessous, la variable a �t� nomm�e �\verb|\par|� ce qui est une chose � ne pas faire. M�me si un dispositif a �t� pr�vu pour que \verb|\par| soit restaur�e � la fin du processus, red�finir une primitive, surtout aussi primordiale que \verb|\par|, \emph{est un danger qu'il faut � tout prix �viter de courir}.

\showcode/\catcode`\@11
\newcount\cnt@nest \cnt@nest=0 % d�finit et initialise le compteur d'imbrication�\idx*\newcount�
\def\end@foreach{\end@foreach}
\long\def\save@macro#1{% sauvegarde la macro #1�\idx*\long�
       \ifdefined#1% si la macro #1 est d�j� d�finie...�\tidx*{ifdefined}�
               \letname{saved@var@\number\cnt@nest}#1% ...la sauvegarder��*\letname�
       \fi
}
\long\def\restore@macro#1{% restaure la macro #1�\idx*\long�
% le \csname donne \relax si la sauvegarde n'a pas �t� faite
       \expandafter\let\expandafter#1\csname saved@var@\number\cnt@nest\endcsname
}
\def\defseplist#1{%��*\deseplist�
       \long\def\doforeach##1\in##2##3{%�\idx*\long�
               \global\advance\cnt@nest1 % entr�e de boucle : incr�menter le compteur d'imbrication�\idx*\global\idx*\advance�
               \save@macro##1% sauvegarde la macro ##1
               \defname{loop@code@\number\cnt@nest}{##3}% assigne le <code> � \loop@code@<n>��*\defname�
               \doforeach@i##1##2#1\end@foreach#1% ajouter ",\end@foreach," et aller � \doforeach@i
               % une fois fini, neutraliser la macro contenant le <code>
               \letname{loop@code@\number\cnt@nest}\empty�\idx*\empty�*\letname�
               \restore@macro##1% restaurer la \<macro>
               \global\advance\cnt@nest-1 % et d�cr�menter le compteur d'imbrication�\idx*\global�
       }%
       \long\def\doforeach@i##1##2#1{%�\idx*\long�
               \def##1{##2}% stocke la valeur en cours dans la \<macro>
               \unless\ifx\end@foreach##1% si la fin n'est pas atteinte�\tidx*{unless}�
                       \antefi% am�ne le \fi ici��*\antefi�
                       \csname loop@code@\number\cnt@nest\endcsname% ex�cute le code�\defline\aaa�
                       \doforeach@i##1% et recommencer
               \fi%
       }%
}
\catcode`@12
\defseplist{,}��*\deseplist�
\doforeach\par\in{a,b,c,y,z}{$\par_i$}

\meaning\par% \par doit �tre redevenu une primitive�\idx*\meaning�

\doforeach\xxx\in{1,2,3}{%
       Ligne \xxx{} : \doforeach\yyy\in{a,b,c,d,e}{(\xxx,\yyy)}.\par
}/

\section{Boucle � deux variables}
Une am�lioration de la macro �\doforeach serait de d�tecter si la variable est seule, comme envisag� pr�c�demment, ou si l'utilisateur souhaite avoir un \emph{couple} de variables auquel cas, il �crirait :

\centrecode-\doforeach\<macro1>/\<macro2>\in{x1/y1,x2/y2,...,xn/yn}{<code>}-

\noindent Chacune des variables \verb|\<macro1>| et \verb|\<macro2>| prendrait successivement les valeurs appari�es sp�cifi�es dans l'argument qui suit le \verb|\in|.

L'id�e va �tre de se servir de la macro �\ifin vue pr�c�demment pour tester si l'argument d�limit� par �\verb|\in|� contient le caract�re �\verb|/|� et agir en cons�quence. Si le test est positif, il faut s'orienter vers une macro � argument d�limit� du type \verb|#1/#2| qui s�pare les deux variables. Nous allons donc, selon l'issue du test \verb|\ifin{#1}{/}|, nous orienter vers la macro vue pr�c�demment si le test est n�gatif ou vers une macro \verb|\doforeach@ii| avec des arguments d�limit�s appropri�s. Nous allons profiter de cette nouvelle fonctionnalit� pour am�liorer et optimiser le code.
\grandsaut

En premier lieu, la macro \verb|\save@macro| effectuera \emph{dans tous les cas} la sauvegarde de la (ou des) variables avec \verb|\let|, que ces variables soient d�finies ou pas. La raison de ce choix, qui implique de se passer du test \tidx{ifdefined}, r�side dans le fait que la variable est rendue \verb|\let|-�gale � \idx\relax � la fin du processus : cela sera \emph{aussi} le cas si la variable est une macro ind�finie. En effet, si une macro $x$ est rendue \verb|\let|-�gale � une macro $y$ non d�finie, $x$ devient �galement non d�finie. Par la suite, si $y$ est rendue \verb|\let|-�gale � $x$ o� la macro $x$ est construite via \idx\csname, la macro $y$ devient \verb|\let|-�gale � \idx\relax

\showcode/\let\foo=\djfhdsldv% \foo est rendue \let-�gale � une macro ind�finie
a) \meaning\foo\par
% puis \djfhdsldv est rendue \let-�gale � \foo (ou \foo est construit avec \csname)
\expandafter\let\expandafter\djfhdsldv\csname foo\endcsname
b) \meaning\djfhdsldv/

L'optimisation que nous pouvons envisager est d'�viter que la macro  \idx\csname (qui est lente) ne se trouve dans une boucle comme c'�tait le cas � la ligne \no\aaa{} du code pr�c�dent. Pour cela, nous allons donner le code � ex�cuter comme argument des macros r�cursives. L'appel initial aux macros r�cursives aura donc la structure suivante :

\centrecode-\doforeach@i{<code>}<var>x1,x2,...,xn,<quark>,-

\noindent ou

\centrecode-\doforeach@ii{<code>}<var1>/<var2>x1/y1,x2/y2,...xn/yn,<quark>/<quark>,-

Ces macros ne liront � chaque it�ration que le \verb|<code>|, la (ou le couple de) variable(s), ainsi que la valeur courante \verb|xi| ou le couple de valeurs courant \verb|xi/yi|. Par cons�quent, l'appel r�cursif sera de la forme

\begin{centrage}
       \small\verb|\doforeach@i{#1}#2|\quad ou\quad \verb|\doforeach@i{#1}#2/#3|
\end{centrage}

\noindent o� \verb|#2| est la variable et \verb|#2/#3| est le couple de variables. Comme les r�cursivit�s sont terminales, les valeurs sont prises dans le code qui reste � lire.

Comme ces macros r�cursives effectuent un test \verb|\ifx| � chaque it�ration pour d�terminer si le \idx{quark} marquant la fin des valeurs est atteint, nous devons nous garder de l'erreur qui consisterait � utiliser �\antefi alors que le \verb|<code>| se situe en �\antefi et \verb|\fi|. Il s'agirait d'une erreur, car si le \verb|<code>| contient un test, l'�\antefi (dont l'argument est d�limit� par \verb|\fi|) prendrait le \verb|\fi| du \verb|<code>| comme d�limiteur et romprait l'appariement correct entre \verb|\ifx| et son \verb|\fi|.

Enfin, il nous faut inventer un moyen de cr�er la macro �\doforeachexit[|(], que l'utilisateur peut �crire dans le \verb|<code>| et qui termine pr�matur�ment toutes les boucles �\doforeach en cours d'ex�cution. Cette macro doit annuler l'appel r�cursif vu ci-dessus. L'id�e directrice est de modifier ces appels r�cursifs de cette mani�re :

\begin{centrage}
       \small\verb|\allow@recurse{\doforeach@i{#1}#2}|\par ou\par \verb|\allow@recurse{\doforeach@i{#1}#2/#3}|
\end{centrage}

\noindent La macro \verb|\allow@recurse| sera rendue \idx\let-�gale � �\identity au d�but de la boucle pour permettre par d�faut que l'appel r�cursif se fasse. Si l'utilisateur ins�re �\doforeachexit dans le \verb|<code>|, \verb|\allow@recurse| doit �tre modifi�e pour que cette derni�re mange tout ce qui reste. � Tout � signifie l'appel r�cursif \emph{et} toutes les valeurs (ou couples de valeurs) restant � lire. Comme ce � tout� se termine forc�ment par le \idx{quark} \verb|\end@foreach| et le s�parateur qui ont �t� ins�r�s par l'appel initial, une macro \verb|\fordib@recurse| � argument d�limit� effectuant cette t�che est facile � cr�er :

\centrecode-\long\def\fordib@recurse##1\end@foreach#1{}-

\noindent Une fois tout ceci mis en place, la macro �\doforeachexit n'a plus qu'� rendre \verb|\allow@recurse| \idx\let-�gale � \verb|\fordib@recurse|.

\showcode|\catcode`\@11
\newcount\cnt@nest \cnt@nest=0 % d�finit et initialise le compteur d'imbrication�\idx*\newcount�
\def\end@foreach{\end@foreach}
\long\def\save@macro#1#2{\letname{saved@var@\number\cnt@nest#1}#2}�\idx*\long�*\letname�
\long\def\save@macro@i#1/#2{\save@macro{a}#1\save@macro{b}#2}
\long\def\restore@macro#1#2{%�\idx*\long�
       \expandafter\let\expandafter#2\csname saved@var@\number\cnt@nest#1\endcsname
}
\long\def\restore@macro@i#1/#2{\restore@macro{a}#1\restore@macro{b}#2}�\idx*\long�
\def\defseplist#1{%��*\deseplist�
       \long\def\doforeach##1\in##2##3{%�\idx*\long �*\doforeach\idx*\long�
               \global\advance\cnt@nest1 % entr�e de boucle : incr�menter le compteur d'imbrication�\idx*\global\idx*\advance�
               \global\let\allow@recurse\identity% permet l'appel r�cursif plus bas�\idx*\global�*\identity�
               \ifin{##1}{/}% si ##1 contient "/"��*\ifin�
                       {\save@macro@i##1% sauvegarde les macros
                       \doforeach@ii% appeler la macro r�cursive avec les arguments
                               {##3}% 1) code � ex�cuter
                               ##1%   2) variables sous la forme \<macro1>/\<macro2>
                               ##2#1\end@foreach/\end@foreach#1% puis la liste ##2 suivie de
                                                               % ",\end@foreach/\end@foreach,"
                       \restore@macro@i##1% une fois sorti de toutes les boucles, restaurer les macros
                       }% si ##1 ne contient pas "/"
                       {\save@macro{}##1% sauvegarde la macro
                       \doforeach@i% appeler la macro r�cursive
                               {##3}% mettre en premier le <code>
                               ##1% puis la variable ##1 en 2e position
                               ##2#1\end@foreach#1% enfin la liste ##2 suivie de ",\end@foreach,"
                       \restore@macro{}##1% une fois sorti de toutes les boucles, restaurer la macro
                       }%
               \global\advance\cnt@nest-1 % d�cr�mente le compteur d'imbrications�\idx*\global\idx*\advance�
       }%
       % ##1 = code � ex�cuter, ##2= variable, ##3=valeur courante
       \long\def\doforeach@i##1##2##3#1{%�\idx*\long�
               \ifx\end@foreach##3% si la fin est atteinte
               \expandafter\gobone\else\expandafter\identity\fi% manger sinon ex�cuter:��*\identity�
                       {\def##2{##3}% fait l'assignation � la variable
                       ##1% le code puis
                       \allow@recurse{\doforeach@i{##1}##2}% recommencer
                       }%
       }%
       % ##1 = code � ex�cuter, ##2/##3= variables, ##4/##5=valeurs courantes
       \long\def\doforeach@ii##1##2/##3##4/##5#1{%�\idx*\long�
               \ifx\end@foreach##4% si la fin est atteinte
               \expandafter\gobone\else\expandafter\identity\fi% manger sinon ex�cuter:��*\identity�
                       {\def##2{##4}\def##3{##5}% fait l'assignation des deux variables
                       ##1% le code puis
                       \allow@recurse{\doforeach@ii{##1}##2/##3}% recommencer
                       }%
       }%
       % macro qui, si elle remplace \allow@recurse, annule l'appel r�cursif
       \long\def\forbid@recurse##1\end@foreach#1{}% tout manger jusqu'� "\end@foreach,"�\idx*\long\defline\aaa�
}
\def\doforeachexit{\global\let\allow@recurse\forbid@recurse}�\idx*\global�
\catcode`\@12
\defseplist{,}��*\deseplist�
\doforeach\par\in{a,b,c,y,z}{$\par_i$}\medskip�\idx*\medskip�

\doforeach\sujet/\terminaison\in{Je/e,Tu/es,Il/e,Nous/ons,Vous/ez,Ils/ent}
       {\sujet\ programm\terminaison{} en \TeX\par}\medskip�\idx*\medskip�

Les voyelles lues sont :
\doforeach\ii\in{a,e,i,o,u,y}{\ii\if o\ii\doforeachexit\fi}.\medskip�\idx*\medskip�

\doforeach\xx\in{a,b,c,d,e,f}
       {\doforeach\ii\in{1,2,3,4}{\xx\ii{} \ifnum\ii=3 \doforeachexit\fi}\par}|

\begin{exercice}
La derni�re boucle imbriqu�e montre que �\doforeachexit sort pr�matur�ment de toutes les boucles en cours.

Comment faudrait-il modifier le code pour que �\doforeachexit ne sorte pr�matur�ment \emph{que} de la boucle dans laquelle elle a �t� appel�e, sans modifier le d�roulement des boucles de niveau sup�rieur ?
\solution
Il faut que \verb|\forbid@recurse|, en plus de manger tout jusqu'� la fin de la liste, rende de nouveau possibles les appels r�cursifs � venir dans d'�ventuelles boucles m�res. Par cons�quent, elle doit redonner � \verb|\allow@recurse| l'�quivalence avec �\identity qu'elle a par d�faut. La ligne \no\aaa{} doit donc �tre

\centrecode-\long\def\forbid@recurse##1\end@foreach#1{\global\let\allow@recurse\identity}-\medskip
\end{exercice}�*\doforeach[|)]�*\doforeachexit[|)]%

\chapter{Dimensions et boites}\idx*[|(]{dimension}
Avec \TeX, tout ce qui touche de pr�s ou de loin � la typographie a une �troite proximit� avec la g�om�trie et le placement des boites qui elles-m�mes, entretiennent de proches rapports avec les dimensions.

Le parti a �t� pris de pr�senter les dimensions (fixes et �tirables) dans un premier temps, quitte � ce que cette th�orie, d�nu�e des objets auxquels elle s'applique, soit un peu r�barbative. Une fois que ces outils et leurs propri�t�s ont �t� d�crits, les boites et les r�glures seront examin�es dans un deuxi�me temps.

\section{Les dimensions fixes}\idx*[|(]{dimension fixe}
\idx*[!dimension|(]{registre}\begin{regle}
Une dimension fixe est utilis�e pour mesurer une longueur prise au sens g�om�trique du terme. \TeX{} dispose de 256 \idx[!dimension]{registre}s de dimension (\numprint{32768} avec \idx\eTeX), chacun capable d'h�berger une dimension. Pour faire r�f�rence � l'un de ces registres, on utilise la primitive \idx\dimen suivie de son num�ro (sous la forme d'un \verb|<entier>|).

Il est possible de demander l'allocation d'un registre inutilis� avec la macro de plain-\TeX{} \idx\newdimen\verb|\<macro>|. La \verb|\<macro>|, d�finie en coulisse par la primitive \idx\dimendef avec

\centrecode-\global\dimendef\<macro>=<nombre>-

sera par la suite �quivalente � \idx\dimen\verb|<nombre>| o� le \verb|<nombre>| est celui du prochain registre libre au moment de l'allocation.

Un \verb|<registre de dimension>| est donc soit une \verb|\<macro>| pr�alablement d�finie � l'aide de \idx\newdimen, soit �\verb|\dimen<nombre>|� o� \verb|<nombre>| est le num�ro du registre de dimension auquel on souhaite faire r�f�rence.

Pour assigner une dimension � un registre de dimension, la syntaxe est

\centrecode-<registre de dimension>= <dimension>-

\noindent o� le signe \verb|=| et l'espace qui le suit sont facultatifs. Pour lire la \verb|<dimension>|, le d�veloppement maximal se met en marche et apr�s d�veloppement, une \verb|<dimension>| est :

\begin{itemize}
       \item une dimension explicitement �crite, c'est-�-dire un \verb|<nombre>| (entier) ou un nombre d�cimal suivi d'espaces facultatifs et de deux lettres de catcode 11 ou 12 repr�sentant une des unit�s de dimensions qu'accepte \TeX{} � savoir \texttt{pt},  \texttt{pc}, \texttt{in}, \texttt{bp}, \texttt{cm}, \texttt{mm}, \texttt{dd}, \texttt{cc}, \texttt{sp}, \texttt{em} et \texttt{ex}. Le s�parateur d�cimal peut indiff�remment �tre le point ou la virgule pourvu que son catcode soit 12. La lecture de la dimension s'arr�te au premier token qui suit les deux caract�res d'unit�. Si ce token est un espace, celui est absorb�.
       \item un \verb|<registre de dimension>|. Si ce registre est pr�c�d� d'un nombre d�cimal sign�, la dimension obtenue sera celle du registre multipli�e par le nombre sign� ;\label{multiplication.dimension}
       \item un \verb|<registre de ressort>| (voir la d�finition � la section suivante) auquel cas, la dimension retenue est �gale � la composante non �tirable du registre de ressort. Si ce registre est pr�c�d� d'un nombre d�cimal sign�, la dimension obtenue sera la composante fixe du ressort multipli�e par le nombre sign�.
\end{itemize}

La valeur absolue maximale d'une \verb|<dimension>| est contenue dans le registre de dimension \idx\maxdimen et vaut \texttt{16383.99999pt}, ce qui repr�sente \texttt{\convertunit{\maxdimen}{cm}cm}.
\end{regle}

Pour ses dimensions, \TeX{} n'est pas avare d'unit�s\idx*[!table des unit�s]{dimension}. Il en manipule 11 dont voici les d�finitions :

\begin{centrage}
\small
\begin{tabular}{c>\ttfamily cr@{${}={}$}lr@{${}={}$}l}
       \idx*{unit�!table} Unit� & \multicolumn1c{Abr�viation} & \multicolumn2c{D�finition} & \multicolumn2c{Exemple}\\\hline
       point\idx*{unit�!pt}\idx*{pt (unit�)} & pt& \multicolumn2c{}&1 \verb|pt| & \showdim{1pt}\\
       pica\idx*{unit�!pc}\idx*{pc (unit�)} & pc & \numprint[pc]1&\numprint[pt]{12} & 1 \verb|pc| & \showdim{1pc}\\
       pouce\idx*{unit�!in}\idx*{in (unit�)} & in & \numprint[in]1&\numprint[pt]{72,27} & 1 \verb|in| & \showdim{1in}\\
       gros point\idx*{unit�!bp}\idx*{bp (unit�)} & bp & \numprint[bp]{72}&\numprint[in]1 & 1 \verb|bp| & \showdim{1bp}\\
       centim�tre\idx*{unit�!cm}\idx*{cm (unit�)} & cm & \numprint[cm]{2,54}&\numprint[in]1 & 1 \verb|cm| & \showdim{1cm}\\
       millim�tre\idx*{unit�!mm}\idx*{mm (unit�)} & mm & \numprint[mm]{10}&\numprint[cm]1 & 1 \verb|mm| & \showdim{1mm}\\
       point didot\idx*{unit�!dd}\idx*{dd (unit�)} & dd & \numprint[dd]{1157}&\numprint[pt]{1238} & 1 \verb|dd| & \showdim{1dd}\\
       cic�ro\idx*{unit�!cc}\idx*{cc (unit�)} & cc & \numprint[cc]1&\numprint[dd]{12} & 1 \verb|cc| & \showdim{1cc}\\
       point d'�chelle\idx*{unit�!sp}\idx*{point d'�chelle}\idx*{sp (unit�)} & sp & \numprint[sp]{65536}&\numprint[pt]1 & $10^6$ \verb|sp| & \showdim{1000000sp}\\
       cadrat\idx*{unit�!em}\idx*{em (unit�)} & em & \multicolumn2c{} & \verb|1em| & \showdim{1em}\\
       hauteur d'\oe il\idx*{unit�!ex}\idx*{ex (unit�)} & ex & \multicolumn2c{} & \verb|1ex| & \showdim{1ex}\\\hline
\end{tabular}
\end{centrage}

Les deux derni�res unit�s d�pendent de la police utilis�e et de sa taille. Historiquement, \verb|1em| est la largeur de la lettre �M�, mais le cr�ateur de la fonte peut en d�cider autrement et donner au \verb|em| une valeur diff�rente. Par exemple, dans la police en cours dans ce paragraphe, \verb|1em| vaut \texttt{\convertunit{1em}{mm}mm} alors que la largeur de la boite englobante de la lettre �M� vaut {\setbox0=\hbox{M}\texttt{\convertunit{\wd0}{mm}mm}}.

La hauteur d'\oe il, ou \verb|ex| est cens�e repr�senter la hauteur des lettres sans hampe, ni jambage ni signe diacritique. Dans la police en cours, \verb|1ex| vaut \texttt{\convertunit{1ex}{mm}mm} et la hauteur de la boite englobante de la lettre �x� vaut \texttt{\setbox0=\hbox{x}\convertunit{\dimexpr\ht0 + \dp0 }{mm}mm}.
\grandsaut

Les \verb|<registres de dimension>|\idx*[!dimension|)]{registre} sont comme les autres registres que nous avons d�j� vus (registres d'entiers ou de tokens) : ce ne sont que des sortes de pointeurs vers une zone de m�moire o� sont �crits les octets capables, selon un proc�d� interne � \TeX, de stocker le contenu du registre. Par cons�quent, dans le code source, un \verb|<registre de dimension>| ne peut �tre �crit seul \emph{que} lorsque \TeX{} s'appr�te � lire une dimension ou lors d'une assignation. Dans les autres cas, la primitive d�veloppable \idx\the, lorsqu'elle pr�c�de le registre, en donne le contenu sous forme de tokens de catcode 12\idx*{catcode!12 (autre)}. Lorsqu'on invoque \idx\the pour faire remonter le contenu d'un registre de dimension des entrailles de \TeX{}, on obtient toujours une dimension en points\idx*{unit�!pt}\idx*{pt (unit�)} o� les caract�res d'unit� �\verb|pt|� ont un catcode de 12. La partie d�cimale est toujours affich�e et �ventuellement r�duite � un 0, et le s�parateur d�cimal est le point. Le nombre de chiffres est au maximum de 5 apr�s la virgule :

\showcode/\newdimen\dimA \newdimen\dimB% alloue deux registres de dimension�\idx*\newdimen�
a) \dimA=59.5pt
  \the\dimA\qquad% doit afficher 59.5pt�\idx*\the�
b) \dimA=1.5cm
  \the\dimA\qquad% convertit � l'affichage 1.5cm en pt
c) \dimB=7pt % assigne 7pt � \dimB
  \dimA\dimB% rend \dimA �gal � dimB
  \the\dimA\qquad
d) \dimA=6\dimB% rend \dimA �gal � 6 fois \dimB
  \the\dimA�\idx*\the�/\grandsaut

Bien qu'�tant traduites en points, toutes ces dimensions ne sont que des multiples de l'unit� de longueur que \TeX{} manipule en interne, le � \idx{point d'�chelle} � (abr�viation �\verb|sp|\idx*{unit�!sp}\idx*{sp (unit�)}� pour � scale point �\idx*{unit�!sp}\idx*{sp (unit�)}), plus petite dimension que \TeX{} peut manipuler et dont la longueur vaut approximativement \hbox{$5{,}4\times10^{-9}$}~m�tre (soit 5,4 nanom�tres). C'est extr�mement petit, de l'ordre de la dimension d'un petit virus. Cette dimension ins�cable, bien �videmment invisible � l'\oe il nu, donne aux calculs sur les longueurs de \TeX{} une grande pr�cision qui restera tr�s inf�rieure � ce qui peut �tre d�cel� � l'\oe il nu, m�me apr�s plusieurs arrondis.

\subsection{Op�rations sur les dimensions}
Comme pour les entiers, des op�rations sont disponibles pour les dimensions via les primitives \idx[|etc]\advance\forbidindex\advance{} pour l'addition, \idx\multiply et \idx\divide pour la multiplication et la division par un entier.

Pour calculer $(25\text{\ttfamily pt}\div4+1,72\text{\ttfamily pt})\times3$, voici comment nous pourrions partir d'une dimension de 25pt, la diviser par 4, ajouter 1.72pt et multiplier le tout par 3 :

\showcode|\newdimen\foo�\idx*\newdimen�
\foo=25pt % assigne 25pt au registre \foo
\divide\foo 4 % le multiplie par 4�\idx*\divide�
\advance\foo1.72pt % lui ajoute 1.72pt�\idx*\advance�
\multiply\foo3 % le multiplie par 3�\idx*\multiply�
\the\foo% affiche la dimension obtenue�\idx*\the�|

\begin{exercice}
�crire une macro �\removept qui retire l'unit� d'une dimension explicite obtenue avec \idx\the. Si la partie d�cimale est nulle, elle ne sera pas affich�e.

\solution
Le premier r�flexe est d'�crire une macro � argument d�limit� par �\verb|pt|� :

\centrecode-\def\removept#1.#2pt{#1\ifnum#2>0 .#2\fi}-�*\removept

Mais cela ne fonctionnera pas puisque les caract�res �\verb|pt|� du \idx{texte de param�tre} n'ont pas le catcode 12\idx*{catcode!12 (autre)}. Il faut donc ruser un peu pour d�finir la macro. Nous pouvons par exemple utiliser une macro temporaire pour stocker �\verb|\def\removept#1.#2pt|� o� les d�limiteurs �\verb|pt|� ont un catcode �gal � 12. Cette macro temporaire sera d�finie par un \idx\edef pour d�velopper �\idx\string\verb| p|� et �\verb|\string t|� qui donnent les caract�res �\verb|pt|� de catcode 12\idx*{catcode!12 (autre)} :

\showcode/\begingroup% ouvrir un groupe
       \edef\temp{\endgroup\def\noexpand\removept##1.##2\string p\string t}%��*\removept\idx*\string�
\temp{#1\ifnum#2>0 .#2\fi}% et le fermer avant de d�finir \removept
\newdimen\foo�\idx*\newdimen�
a) \foo=15pt \expandafter\removept\the\foo\qquad�\idx*\the�
b) \foo=3.14pt \expandafter\removept\the\foo��*\removept�/

L'astuce consiste � inclure le \idx\endgroup dans le texte de remplacement de \verb|\temp| de telle sorte que lorsque \verb|\temp| se d�veloppe puis s'ex�cute, ce \idx\endgroup provoque la destruction de cette macro temporaire avant m�me d'avoir fini de lire son texte de remplacement.

Il est naturel de cr�er la macro �\dimtodec qui transforme un registre de dimension en nombre d�cimal :

\showcode/\def\dimtodec{\expandafter\removept\the}��*\dimtodec�*\removept�
\newdimen\foo�\idx*\newdimen�
a) \foo=15pt \dimtodec\foo \qquad
b) \foo=3.14pt \dimtodec\foo��*\dimtodec�/
\end{exercice}

\subsection{La primitive \texttt{\textbackslash dimexpr}}
La primitive \idx\dimexpr\label{dimexpr} de \idx\eTeX{} est aux calculs sur dimensions ce que \idx\numexpr est aux calculs sur les entiers. Elle rend possibles des calculs sur les dimensions de \TeX{} sans passer par les registres de dimension et les primitives \idx\advance, \idx\multiply et \idx\divide qui donnent un code assez fastidieux.

\begin{regle}
La primitive \idx\dimexpr de \idx\eTeX{} doit �tre suivie d'un enchainement d'op�rations sur des dimensions qui est �valu� selon les r�gles math�matiques habituelles : parenth�ses, op�rations (\verb|+|, \verb|*|, \verb|/|), priorit�s. Cette primitive poss�de les propri�t�s suivantes :

\begin{itemize}
       \item tout comme \idx\numexpr, \idx\dimexpr amorce un d�veloppement maximal pour �valuer l'\verb|<expression>| qui la suit. L'\verb|<expression>| prend fin au premier caract�re qui ne peut faire partie d'un calcul sur les dimensions. La primitive \idx\relax peut marquer la fin d'une \verb|<expression>| et dans ce cas, elle est absorb�e par \idx\dimexpr;
       \item les espaces dans l'\verb|<expression>| sont ignor�s ;
       \item dans l'\verb|<expression>|, une \verb|<dimension>| ne peut �tre multipli�e ou divis�e (avec \verb|*| ou \verb|/|) que par un \emph{entier}. Dans ce cas, l'entier \emph{doit} �tre l'op�rateur c'est-�-dire qu'il doit suivre la dimension. On doit donc �crire

       \begin{centrage}\verb-<dimension>*<entier>- ou \verb-<dimension>/<entier>-\end{centrage}
       \item une \verb|<expression>| �valu�e par \idx\dimexpr est du m�me type qu'un registre de dimension, il s'agit donc d'une repr�sentation \emph{interne} d'une dimension. On peut convertir cette repr�sentation interne en caract�res de catcode 12\idx*{catcode!12 (autre)} en faisant pr�c�der \idx\dimexpr de la primitive d�veloppable \idx\the.
\end{itemize}
\end{regle}

Voici quelques exemples o� la primitive \idx\dimexpr est mise � contribution :

\showcode|a) \the\dimexpr 1cm + 0.5cm\relax \qquad�\idx*\dimexpr�
b) \the\dimexpr 1pt + 1pt\relax \qquad�\idx*\the�
c) \the\dimexpr 1pt + 2pt * 3\relax\qquad
d) \the\dimexpr (1pt + 2pt) * 3\relax\qquad
e) \the\dimexpr (1.2pt + 0.8pt) * 5\relax\qquad
f) \newdimen\foo \foo=15pt �\idx*\newdimen�
  \the\dimexpr\foo-(\foo + 1pt) / 4\relax|

\subsection{Les limites du calcul sur les dimensions}\label{arrondis.sur.dimensions}\idx*[|(]{dimension!arrondi}\idx*[|(]{arrondi (dimension)}
Tout semble se passer pour le mieux et il serait tentant de penser qu'une fois lib�r�e de son unit� en \verb|pt|, une dimension se comporte exactement comme un nombre d�cimal tandis que de son c�t�, \idx\dimexpr joue le r�le de machine � calculer. La simple addition ci-dessous va temp�rer ce jugement :

\showcode/\the\dimexpr0,7pt + 0.4pt\relax�\idx*\the\idx*\dimexpr�/

\Qu e se passe-t-il et pourquoi le simple calcul �\texttt{0,7pt + 0.4pt}� ne donne-t-il pas comme r�sultat \texttt{1.1pt}? Les calculs de dimensions seraient-ils bogu�s ? La r�ponse est bien �videmment non, mais c'est le revers de la m�daille : puisque toutes les dimensions sont converties en �\verb|sp|\idx*{unit�!sp}\idx*{sp (unit�)}� en interne pour effectuer les calculs puis sont � nouveau converties en �\verb|pt|� pour le r�sultat, des arrondis sont in�vitablement faits lors de ces deux conversions. Il faut donc s'attendre � ce que ces arrondis viennent dans certains cas se cumuler d�favorablement. Voici l'explication de l'erreur constat�e :

\begin{itemize}
       \item \verb|0,7pt| vaut $0,7\times\numprint{65536}=\numprint[sp]{45875.2}$ qui est arrondi � \numprint[sp]{45875}\idx*{unit�!sp}\idx*{sp (unit�)};
       \item \verb|0.4pt| vaut $0.4\times\numprint{65536}=\numprint[sp]{26214.4}$ qui est arrondi � \numprint[sp]{26214};
       \item en tenant compte des arrondis, la somme vaut $\numprint{45875}+\numprint{26214}=\numprint[sp]{72089}$;
       \item convertie en pt, cette somme vaut $\numprint{72089}\div65536=\numprint{1,09999084473}$ et \TeX{} donne 5 chiffres apr�s la virgule ce qui fait bien \numprint[pt]{1.09999}.
\end{itemize}

Le r�sultat attendu, \verb|1.1pt| vaut $\numprint{1.1}\times{65536}=\numprint[sp]{72089.6}$ qui serait arrondi par \TeX{} � \numprint[sp]{72090}\idx*{unit�!sp}\idx*{sp (unit�)}.

Si une dimension est consid�r�e comme une mesure de ce qui doit �tre affich�, ces erreurs d'arrondis sont absolument insignifiantes puisqu'invisibles � l'\oe il nu; insistons sur le fait qu'il ne s'agit ici que d'une minuscule erreur d'\verb|1sp|\idx*{unit�!sp}\idx*{sp (unit�)} c'est-�-dire de quelques nanom�tres ! Mais pour le programmeur, c'est la douche froide et c'est l'assurance que les dimensions ne peuvent pas jouer le r�le de nombres d�cimaux pris en tant que nombres \emph{math�matiques}, car une erreur sur une simple addition est inacceptable. On peut donc affirmer que \TeX{} ne dispose de rien qui pourrait tenir lieu de nombres d�cimaux comme en disposent les autres langages. Bien �videmment, on peut \emph{programmer} le fonctionnement de nombres d�cimaux (en virgule fixe ou flottante) avec les outils de base de \TeX{} que sont les entiers et les 4 op�rations. Construire des op�rations sur ces nombres est extr�mement fastidieux\footnote{L'extension �\texttt{\idx*{package!fp}fp}� (pour �fixed point�) a relev� ce d�fi. Cette extension est programm�e en \TeX{} et utilise les compteurs pour parvenir � ses fins. Elle d�finit et manipule des nombres en virgule \emph{fixe} avec une partie enti�re et une partie d�cimale de 18 chiffres chacune et effectue toutes les op�rations arithm�tiques et scientifiques habituelles sur ces nombres en virgule fixe (puissances, exponentielles, logarithmes, lignes trigonom�triques, tests, nombres pseudoal�atoires, etc.). Ainsi, il est tr�s facile de calculer que

\[\frac{\mathrm e^4 \ln\left(1+\cos\frac\pi7\right)}{1-3\arctan(0.35)}+4\sqrt[3]{5+\sqrt{2}}\approx-3491.19785321755\mathbf{4299238}
\]

Du fait d'arrondis successifs dans cette expression complexe, les d�cimales en gras sont fausses% et devraient �tre 5016987
}\idx*[|)]{dimension!arrondi}\idx*[|)]{arrondi (dimension)}. Il faut mentionner la macro purement d�veloppable �\decadd, programm�e en annexe (voir page~\pageref{decadd}), qui permet d'additionner de fa�on \emph{exacte} deux nombres d�cimaux sign�s.

Il est primordial de comprendre qu'une dimension et un nombre entier ne sont que deux facettes d'une m�me chose : puisque tous les calculs se font en nombre entier de points d'�chelle\idx*{point d'�chelle}, une dimension en \TeX{} n'est en r�alit� que le nombre \emph{entier} de \verb|sp|\idx*{unit�!sp}\idx*{sp (unit�)} qu'elle repr�sente !

\begin{regle}
Toutes les dimensions fixes que \TeX{} manipule sont converties en interne en le nombre \emph{entier} de \idx*{point d'�chelle}points d'�chelle (\verb|sp|\idx*{unit�!sp}\idx*{sp (unit�)}) qu'elles repr�sentent. Une dimension s'apparente donc � un entier.

Si \TeX{} est � un endroit o� il s'attend � lire un \verb|<nombre>| entier et qu'il lit un \verb|<registre de dimension>|, il convertit la dimension contenue dans le registre en � \idx{entier contraint} � qui est le nombre de \verb|sp|\idx*{sp (unit�)}\idx*{unit�!sp} qu'elle repr�sente. Cet entier contraint est le \verb|<nombre>| qui sera  pris en compte.
\end{regle}

Constatons-le avec ce code o� la primitive \idx\number qui, attendant un nombre entier, force la conversion de la dimension en \idx{entier contraint} :

\showcode/a) \newdimen\foodim \foodim=1cm \number\foodim\relax\qquad�\idx*\newdimen�
b) \number\dimexpr 0.7pt + 0.4pt\relax\qquad�\idx*\number�
c) \number\dimexpr 1.1pt\relax/

\begin{exercice}
La macro \verb|\for|, programm�e � la page~\pageref{for}, ne peut manipuler que des nombres \emph{entiers}.

Sur le mod�le de �\for, cr�er une macro �\FOR o� les nombres (borne mini, maxi et incr�ment) peuvent �tre d�cimaux.

On utilisera le test \tidx{ifdim}, de syntaxe

\centrecode-\ifdim<dimension1><signe de comparaison><dimension2>
       <code vrai>
\else
       <code faux>
\fi-

qui est aux \verb|<dimensions>| ce que le test \verb|\ifnum| est aux entiers.
\solution
Il y a peu de changements � faire. Il faudra remplacer les tests \tidx{ifnum} par \tidx{ifdim} et rajouter l'unit� \verb|pt| lorsque c'est n�cessaire.

\showcode/\catcode`\@11
\def\FOR#1=#2to#3\do#4#{%
       \ifempty{#4}��*\ifempty�
               {\let\FOR@increment\z@}
               {\edef\FOR@increment{\the\dimexpr#4pt\relax}}% lit et normalise l'argument optionnel
       \ifdim\FOR@increment=\z@% s'il est nul,�\idx*\z@�
               \edef\FOR@increment{% le red�finir � -1pt (si #3<#2) et 1pt sinon
                       \ifdim\dimexpr#3pt-#2pt\relax<\z@ -1\else 1\fi pt�\idx*\numexpr\idx*\z@�
               }% \FOR@increment vaut donc 1 ou -1
       \fi
       \ifdim\dimtodec\dimexpr#3pt-#2pt\relax\dimexpr\FOR@increment\relax<\z@�\defline\aaa�
               \expandafter\gobone% si argument optionnel incompatible, manger le {<code>}
       \else
               \edef#1{\dimtodec\dimexpr#2pt\relax}% initialise la \<macro>
               \edef\macro@args{% d�finit et d�veloppe les arguments � passer � \FOR@i
                       %#1=nom de la macro r�cursive :
                       \expandafter\noexpand\csname FOR@ii@\string#1\endcsname�\idx*\csname\idx*\endcsname\idx*\string�
                       \ifdim\FOR@increment<\z@ <\else >\fi% #2=signe de comparaison�\idx*\z@�
                       {\FOR@increment}% #3=incr�ment
                       \noexpand#1% #4=\<macro>�\idx*\noexpand�
                       {\the\dimexpr#3pt\relax}% #5=dimension n2�\idx*\number\idx*\numexpr�
               }%
               \antefi% externalise la ligne ci-dessous de la port�e du test��*\antefi�
               \expandafter\FOR@i\macro@args% appelle \FOR@i avec les arguments d�finis ci-dessus
       \fi
}

% #1=nom de la macro r�cursive de type "\FOR@ii@\<macro>"
% #2=signe de comparaison  % #3=incr�ment
% #4=\<macro>  % #5=dimension n2  % #6=<code> � ex�cuter
\long\def\FOR@i#1#2#3#4#5#6{%�\idx*\long�
       \def#1{% d�finit la sous macro r�cursive
               \unless\ifdim#4pt#2#5\relax% tant que la \<macro> variable n'a pas d�pass� n2�\tidx*{unless}�
                       \afterfi{% rendre la r�cursivit� terminale��*\afterfi\idx*{r�cursivit�!terminale}�
                               #6% ex�cute le code�\defline\bbb�
                               \edef#4{\dimtodec\dimexpr#4pt+#3\relax}% incr�mente la \<macro>
                               #1% recommence
                       }%
               \fi
       }%
       #1% appelle la sous-macro r�cursive�\defline\ccc�
}%
\def\exitFOR#1{% #1=\<macro> correspondant � la boucle de laquelle on veut sortir��*\exitFOR�
       \defname{FOR@ii@\string#1}{}%�\idx*\csname\idx*\endcsname\idx*\string�*\defname�
}

\def\ifexitFOR#1{% envoie vrai si on est pr�matur�ment sorti de la boucle de \<macro> #1��*\ifexitFOR�
       % si la macro r�cursive est \empty
       \expandafter\ifx\csname FOR@ii@\string#1\endcsname\empty�\idx*\string\idx*\empty�
               \expandafter\firstoftwo% c'est qu'on est sortir pr�matur�ment, renvoyer "vrai"��*\firstoftwo�
       \else
               \expandafter\secondoftwo% sinon, renvoyer "faux"��*\secondoftwo�
       \fi
}
\catcode`\@=12
a) \FOR\xx=1.5 to -5\do-1{"\xx" }\par

b) \FOR\ii=1 to 2.742\do.25{"\ii" }\par

c) \FOR\ii=0 to 1\do0.1{"\ii" \ifdim\ii pt>0.5pt \exitFOR\ii\fi}��*\FOR�/

La ligne \no\aaa{} m�rite tout de m�me quelques explications. Il s'agit de trouver le signe de

\[(\hbox{\verb|#3|}-\hbox{\verb|#2|})\times\hbox{\verb|\for@increment|}\]

Pour calculer cette expression sous forme de dimension, nous avons tout d'abord transform� \verb|#3-#2| en un d�cimal sans unit� avec la macro �\dimtodec. La macro \verb|\for@increment| est transform�e en une dimension de type \verb|<registre>| avec \idx\dimexpr. Le test \tidx{ifdim} voit donc \verb|<x><registre de dimension>| o� \verb|<x>| est un d�cimal sign�. Comme l'explique la r�gle vue pr�c�demment, le tout forme une \verb|<dimension>| �gale au produit de \verb|#3-#2| par \verb|\for@increment|.

Comme le montre le cas c, additionner � chaque it�ration l'incr�ment � la dimension pr�c�dente conduit parfois � des erreurs d'arrondi g�nantes. Pour une addition d�cimale \emph{exacte}, voir en annexe la macro �\decadd, page~\pageref{decadd}.
\end{exercice}

\subsection{�tendre les calculs sur les dimensions}
Puisqu'il n'est pas question d'�crire une extension aussi complexe que \verb|fp|, nous allons accepter les erreurs d'arrondis dues � la m�thode de calcul sur les dimensions. Aussi, nous allons confondre dimension en \verb|pt| sans unit� et nombre d�cimal; en effet, passer de l'une � l'autre est facile. Il suffit d'appeler la macro �\dimtodec pour le sens \emph{dimension vers d�cimal} ou d'ajouter l'unit� \verb|pt| pour le sens inverse.

Nous allons essayer de tirer parti de \idx\dimexpr et des r�gles que nous avons vues pour �tendre un peu les possibilit�s de calcul de \TeX{} sur les nombres d�cimaux. Si l'addition et la soustraction op�rent sur \emph{deux} nombres d�cimaux, il n'en est pas de m�me pour la multiplication et la division qui ne sont capables de multiplier ou diviser par un \emph{entier}.

\subsubsection{Multiplier deux d�cimaux}
Essayons tout d'abord de programmer une macro �\decmul qui permet de multiplier deux nombres \emph{d�cimaux}, chacun se trouvant dans un argument.

Nous allons exploiter le fait que \verb|<d�cimal><registre de dimension>| est vue comme une dimension �gale au produit des deux quantit�s.

\showcode/\newdimen\foo�\idx*\newdimen�
\foo=15.2pt \foo=1.5\foo \the\foo% vaut 15.2*1.5�\idx*\the�/

Aux erreurs d'arrondi pr�s auxquelles nous nous sommes r�sign�s, le r�sultat est correct. Voici donc comment programmer la macro �\decmul\label{decmul} :

\showcode/\catcode`\@11
\newdimen\dim@a�\idx*\newdimen�
\def\decmul#1#2{%��*\decmul�
       \dim@a=#2pt    % range la dimension #2pt dans le registre de dimension
       \dim@a=#1\dim@a% multiplier le registre par le d�cimal #1
       \dimtodec\dim@a% convertir la dimension en d�cimal��*\dimtodec�
}
\catcode`\@12
a) \decmul{15.2}{1.5}\qquad
b) \decmul{48.2}{.375}��*\decmul�/

\begin{exercice}
La macro �\decmul programm�e ci-dessus n'est pas purement d�veloppable. Utiliser la primitive \idx\dimexpr pour qu'elle le devienne.
\solution
La m�thode va �tre de donner � �\dimtodec non pas un vrai registre de dimension, mais une expression �valu�e par \idx\dimexpr, puisque cette primitive est du m�me type qu'un registre de dimension :

\centrecode-\dimtodec\dimexpr<expression>\relax-

En ce qui concerne l'\verb|<expression>|, nous allons utiliser la m�me m�thode vue ci-dessus, � savoir \verb|#1<registre>| o� le \verb|<registre>| sera remplac� par \idx\dimexpr\verb|#2\relax|. Cela donne :

\showcode/\def\decmul#1#2{\dimtodec\dimexpr#1\dimexpr#2pt\relax\relax}��*\decmul �*\dimtodec\idx*\dimexpr�

a) \decmul{15.2}{1.5}\qquad
b) \edef\foo{\decmul{48.2}{.375}}\meaning\foo��*\decmul�/
\end{exercice}

\subsubsection{Diviser par un d�cimal}
Si nous souhaitons �crire une macro analogue �\decdiv[|(]\verb|{<nba>}{<nbb>}| qui effectue la division du d�cimal \verb|<nba>| par le d�cimal \verb|<nbb>|, l'astuce consiste � �valuer avec \idx\numexpr l'entier suivant :

\[
\frac{\text{\texttt{\codeelement{nba}pt}}\times\text{\ttfamily 1pt}}{\text{\texttt{\codeelement{nba}pt}}}
\]

\noindent Comme \idx\numexpr s'attend � des op�rations sur des entiers, chaque dimension, pr�alablement mise sous forme de registre avec \verb|\dimexpr|, sera convertie en entier contraint. Le risque de d�passement de l'entier maximal au num�rateur est improbable, car lorsque \idx\numexpr (tout comme \idx\dimexpr) effectue une multiplication imm�diatement suivie d'une division, les calculs internes se font sur 64 bits et non sur 32.

Une fois cet entier calcul�, nous lui donnerons l'unit� \verb|sp|\idx*{unit�!sp}\idx*{sp (unit�)} et �valuerons le tout avec \idx\dimexpr. Le r�sultat, expurg� de son unit� avec �\dimtodec, donnera le quotient cherch�.

Pour �viter un \idx\dimexpr inutile, la dimension \verb|1pt|, qui vaut \verb|65536sp|, a �t� directement convertie en l'entier contraint \verb|65536| :

\showcode|\def\decdiv#1#2{% divise le d�cimal #1 par le d�cimal #2��*\decdiv�
       \dimtodec��*\dimtodec\idx*\dimexpr\idx*\numexpr�
       \dimexpr
               \numexpr
                       \dimexpr #1pt \relax * 65536 / \dimexpr #2pt \relax
               \relax
               sp�\idx*{sp (unit�)}\idx*{unit�!sp}\idx*{sp (unit�)}�
       \relax
}

1) \decdiv{4.5}{0.075}\qquad% doit donner 60
2) \decdiv{8}{0.1}\qquad% doit donner 80
3) \decdiv{3.14}{1.6}\qquad% doit donner 1.9625
4) \decdiv{687.59829}{5.29871}\qquad% doit donner 129.76706
4) \edef\foo{\decdiv{0.37}{2.5}}\foo% doit donner 0.148��*\decdiv�|

Ici encore, il ne s'agit que d'arithm�tique \TeX ienne, c'est-�-dire que comme avec �\decmul, les r�sultats sont entach�s d'erreurs d'arrondis et donc, ces macros ne pourront �tre utilis�es que pour des calculs de dimensions et non pas pour des calculs sur des nombres pris en tant qu'entit�s math�matiques�*\decdiv[|)].

\begin{exercice}
�crire une macro �\convertunit[|(] de syntaxe

\centrecode-\convertunit{<dimension>}{<unit�>}-

qui convertit la \verb|<dimension>| dans l'\verb|<unit�>| sp�cifi�e par les deux caract�res caract�risant chaque unit�, et d'afficher le r�sultat sans unit�. La macro devra �tre purement d�veloppable.

\solution
Nous allons proc�der comme nous l'avons fait avec la macro �\decdiv : nous allons mettre \idx\numexpr � contribution pour transformer en \idx{entier contraint} toutes les dimensions et multiplier la \verb|<dimension>| par \verb|1pt| et diviser le tout par
\verb|1<unit�>| :

\showcode|\def\convertunit#1#2{%��*\dimtodec�
       \dimtodec
       \dimexpr
               \numexpr
                       \dimexpr #1 \relax * 65536 / \dimexpr 1#2 \relax
               \relax
               sp
       \relax
}

a) \convertunit{15cm}{mm}\qquad
b) \convertunit{9,14in}{cm}\qquad
c) \convertunit{100000sp}{mm}\qquad
d) \convertunit{160.5pt}{cm}\qquad
e) \edef\foo{\convertunit{2,5cm}{cc}}\meaning\foo|
�*\convertunit[|)]\end{exercice}\idx*[|)]{dimension fixe}

\section{Les dimensions �tirables ou ressorts}\idx*[|(]{registre!ressort}\idx*[|(]{dimension �tirable (ressort)}
\subsection{\Qu'est-ce qu'un ressort ?}
Int�ressons-nous maintenant aux ressorts qui ont vocation � remplir des zones susceptibles d'avoir des tailles variables (souvent pour des raisons typographiques).

\begin{regle}
Un ressort est une dimension assortie de composantes �tirables optionnelles (�ventuellement infinies) de sorte qu'il peut, selon le contexte et sa d�finition, se comprimer ou s'�tirer. \TeX{} offre 256 registres de ressorts et ce nombre monte � \numprint{32768} avec \idx\eTeX. La primitive \idx\skip suivie d'un \verb|<nombre>| permet d'acc�der � un registre sp�cifique par son num�ro.

Plain-\TeX{} fournit la macro \idx\newskip\verb|\<macro>| qui met � profit la primitive \idx\skipdef selon cette syntaxe

\centrecode-\skipdef\<macro>=<nombre>-

pour rendre cette \verb|\<macro>| �quivalente � \idx\skip\verb|<nombre>|, o� le \verb|<nombre>| est celui du prochain registre libre. D�s lors, un \verb|<registre de ressort>|\idx*{registre!ressort} est soit \idx\skip suivi d'un num�ro, soit une \verb|\<macro>| pr�alablement d�finie par \idx\newskip.

Pour assigner un ressort � un \verb|<registre de ressort>|, il faut �crire :

\centrecode-<registre de ressort>= <ressort>-

\noindent o� le signe �\verb|=|� et l'espace qui le suit sont optionnels. Pour lire le \verb|<ressort>|, le d�veloppement maximal se met en marche. Un \verb|<ressort>| est une \verb|<dimension>| �ventuellement suivie d'une composante d'�tirement optionnelle de la forme �\verb|plus <�tirement>|� puis d'une composante de compression optionnelle de la forme �\verb|minus <�tirement>|�.

Si elles sont pr�sentes toutes les deux, ces deux composantes optionnelles doivent \emph{n�cessairement} �tre d�clar�es dans cet ordre. Si elles ne sont pas sp�cifi�es, les composantes �tirables valent \verb|0pt| par d�faut.

Un \verb|<�tirement>| est :\label{dimension.ressort}\idx*{registre!ressort!�tirement}
\begin{itemize}
       \item soit une composante fixe qui est une \verb|<dimension>| comme �\verb|1.5pt|� ou �\verb|0.25cm|�;
       \item soit une composante infinie qui prend la forme d'un coefficient d'infini suivi de �\verb|fil|�, �\verb|fill|� ou �\verb|filll|�, o� ces 3 mots-cl� repr�sentent des infinis de \emph{forces} diff�rentes : �\verb-filll-� est infiniment plus grand que �\verb|fill|�, quels que soient les coefficients qui les pr�c�dent et de la m�me fa�on, �\verb|fill|� est infiniment plus grand que �\verb|fil|�.

       Le coefficient d'infini est un d�cimal sign� dont la valeur absolue peut prendre toutes les valeurs entre 0 et \verb|16383.99999|.
\end{itemize}
\end{regle}\idx*[|(]{registre!ressort!�tirement}

� la mani�re de \idx\dimexpr qui fait des calculs sur les dimensions, la primitive \idx\glueexpr effectue des calculs sur les ressorts :

\showcode|\the\glueexpr 5pt plus 2pt minus 1.5pt + 7pt plus0.5pt minus 3pt\relax \par�\idx*\glueexpr\idx*\the�
\the\glueexpr 25pt plus2fil + 35pt plus 0.1fill\relax|
\grandsaut

Envisageons maintenant quelques exemples pour mieux comprendre comment les ressorts fonctionnent et quelles sont leurs � forces � relatives.

Int�ressons-nous tout d'abord aux composantes d'�tirement finies. Le ressort �\texttt{10pt plus1.5pt minus 2.5pt}� a une longueur naturelle de \numprint[pt]{10} mais peut s'allonger jusqu'� \numprint[pt]{11.5} et se comprimer jusqu'� \numprint[pt]{7.5}. De la m�me fa�on, le ressort �\texttt{0pt minus5pt}� a une longueur naturelle nulle, mais peut se comprimer jusqu'� une longueur n�gative de \numprint[pt]{-5}.

Venons-en aux composantes d'�tirement infinies. Supposons qu' un ressort $R_1$ soit �gal � �\texttt{1.5cm plus2fill}�. Il a une longueur naturelle de \numprint[cm]{1.5} et peut s'allonger autant que n�cessaire comme le sp�cifie sa composante �tirable. Si un autre ressort $R_2$ est d�fini par �\texttt{2.5cm plus3fill}� et si nous demandons � ces deux ressorts de remplir un espace de \numprint[cm]{10}, la longueur � combler est de \numprint[cm]{6} puisque la somme des deux longueurs naturelles vaut \numprint[cm]{4}. Le ressort $R_1$ s'allongera de 2/5 la longueur � combler et $R_2$ de 3/5 de cette longueur, comme le sp�cifient les coefficients d'infini. $R_1$ mesurera  $1.5+6\times2/5=\numprint[cm]{3.9}$ alors que $R_2$ mesurera $2.5+6\times3/5=\numprint[cm]{6.1}$. En voici l'illustration ci-dessous o� les dimensions naturelles sont en traits pleins et les �tirements en pointill�s. Si aucune op�ration dans l'impression de ce livre n'a provoqu� d'alt�ration d'�chelle, les dimensions donn�es ci-dessus doivent exactement se retrouver dans ce sch�ma :

\begingroup
\medbreak
\ttfamily
\small
\hfill
\leavevmode\lower5pt\hbox{\hbox to1.5cm{\hss 1.5cm\kern2pt}\hbox to2.4cm{\kern2pt plus 2fill\hss}\hbox to2.5cm{\hss2.5cm\kern2pt}\hbox to 3.6cm{\kern2pt plus 3fill\hss}}\hfill\null

\hfill\vrule width0.4pt height 1ex depth 0pt
\vrule width1.5cm height0.4pt depth 0pt
\vrule width0.2pt height 1ex depth 0pt
\hbox to2.4cm{\xleaders\hbox{\vrule width2pt height.4pt\kern1pt }\hfill}%
\vrule width0.4pt height 1ex depth 0pt
\vrule width2.5cm height0.4pt depth 0pt
\vrule width0.4pt height 1ex depth 0pt
\hbox to3.6cm{\xleaders\hbox{\vrule width2pt height.4pt\kern1pt }\hfill}%
\vrule width0.4pt height 1ex depth 0pt \hfill\null
\medbreak\endgroup

Enfin, si un ressort $R_3$ �gal � �\texttt{3cm plus 20fil}� et un ressort $R_4$ �gal � �\texttt{2cm plus 0.1fill}� doivent combler un espace de \numprint[cm]{20}, seul $R_4$ s'allongera pour mesurer \numprint[cm]{17} car son infini �\verb|fill|� est infiniment plus grand que �\verb|fil|�.\idx*[|)]{registre!ressort!�tirement}

\subsection{Ins�rer des espaces de dimensions choisies}
\subsubsection{Insertion d'espaces ins�cables}
\begin{regle}
Pour ins�rer une espace ins�cable, on utilise la primitive \idx\kern suivie d'une \verb|<dimension>| qui sera celle de l'espace ins�r�e.

L'espace sera ins�r�e dans le mode en cours : elle sera horizontale si \TeX{} est en mode horizontal\idx*{mode!horizontal} � ce moment-l� et sera verticale s'il est en mode vertical\idx*{mode!vertical}.

L'espace ainsi cr�� est \emph{ins�cable} car aucune coupure de ligne ou de page ne pourra s'y faire.
\end{regle}

\showcode/foo% les caract�res font entrer TeX en mode horizontal�\idx*{mode!horizontal}�
\kern0.5cm % espace ins�r�e en mode horizontal�\idx*{mode!horizontal}�
bar\par% \par fait passer en mode vertical�\idx*{mode!vertical}�
\kern0.5cm % espace ins�r�e en mode vertical
boo/

L'espace verticale entre la fronti�re basse de �bar� et la fronti�re haute de �boo� n'est pas \verb|0.5cm|, car le ressort d'interligne vient s'ajouter � la dimension ins�cable ins�r�e par \idx\kern.

\subsubsection{Insertion d'espaces s�cables}
� la diff�rence des espaces ins�cables, un espace est dit � \emph{s�cable} � s'il peut c�der sa place � une coupure (de ligne ou de page). Le verbe � c�der � sugg�re que si une coupure est faite, l'espace est retir� de la liste en cours et est remplac� par une coupure.

\begin{regle}
La primitive \idx\hskip, suivie d'un \verb|<ressort>| ins�re une espace (dont les dimensions sont celles permises par le ressort\idx*{registre!ressort}) dans la liste horizontale en cours. La primitive \idx\vskip en est le pendant pour le mode vertical\idx*{mode!vertical}.

Si \TeX{} rencontre une de ces deux primitives et ne se trouve pas dans le mode qu'elles exigent, alors le mode courant se termine et \TeX{} passe dans le mode requis.

Les espaces ainsi ins�r�es sont s�cables, c'est-�-dire susceptibles d'�tre remplac�es par des coupures de ligne ou de pages. De plus, elles sont ignor�es lorsqu'elles se trouvent imm�diatement avant la fin du \idx[!espaces ignor�s]{paragraphe} pour \idx\hskip ou de la fin de la page pour \idx\vskip.
\end{regle}

Il est utile de savoir qu'en mode horizontal\idx*{mode!horizontal}, le token espace (de catcode 10\idx*{catcode!10 (espace)} et de code de caract�re 32) se comporte comme un ressort\idx*{registre!ressort} : il a une dimension naturelle et peut, dans une certaine mesure, se comprimer ou se dilater (lire page~\pageref{espace.dimensions.fonte}).
\grandsaut

Certaines primitives sont en r�alit� des ressort\idx*{registre!ressort}s. Il est important de distinguer deux types de � ressorts-primitives � :

\begin{itemize}
       \item ceux qui sont \emph{modifiables} et qui se comportent comme une macro d�finie avec \idx\newskip. Ces ressorts-primitives sont susceptibles de recevoir un \verb|<ressort>| par assignation. La plupart de ces ressorts-primitives concernent des r�glages typographiques;
       \item ceux, non modifiables, dont la valeur est pr�d�finie et invariable.
\end{itemize}

Le tableau ci-dessous, sans �tre exhaustif, liste quelques ressorts utilis�s par \TeX{}, qu'ils soient de simples macros d�finies avec \idx\newskip (partie du haut), des ressorts-primitives modifiables (�crits en gras dans la partie du milieu) ou ressorts-primitives non modifiables (pr�c�d�s d'une �$*$� dans la partie basse).

Dans chaque cat�gorie, la valeur par d�faut assign�e par plain-\TeX{} ou le comportement (pour les ressorts-primitives non modifiables) est donn� dans la colonne � D�finition �  tandis que le mode dans lequel le \idx*{registre!ressort}ressort est utilis� est donn� dans la colonne de droite.\medbreak

\begingroup
       \small
       \LTpre2\parskip \LTpost\parskip\label{tableau.ressort}%
       \begin{longtable}{>\ttfamily r@{}c@{}>\ttfamily l@{\kern1em}c}\hline
               Nom && D�finition & Mode\\\hline\endhead
               \idx\hideskip&${}={}$&-1000pt plus 1fill& h\\
               \idx\centering&${}={}$&0pt plus 1000pt minus 1000pt& h\\
               \idx\z@skip&${}={}$&0pt plus0pt minus0pt& h ou v\\
               \idx\smallskipamount&${}={}$&3pt plus 1pt minus 1pt&v\\
               \idx\medskipamount&${}={}$&6pt plus 2pt minus 2pt&v\\
               \idx\bigskipamount&${}={}$&12pt plus 4pt minus 4pt&v\\\hline
               \bfseries\idx\baselineskip&${}={}$&12pt&v\\
               \bfseries\idx\lineskip&${}={}$&1pt&v\\
               \bfseries\idx\leftskip&${}={}$&0pt&h\\
               \bfseries\idx\rightskip&${}={}$&0pt&h\\
               \bfseries\idx\parskip&${}={}$&0pt plus 1pt& v\\
               \bfseries\idx\parfillskip&${}={}$&0pt plus 1fil& h\\\hline
               \llap{${}^*$}\idx\hfil&${}\equiv{}$&\string\hskip{} 0pt plus 1fil&h\\
               \llap{${}^*$}\idx\hfilneg&${}\equiv{}$&\string\hskip{} 0pt plus -1fil&h\\
               \llap{${}^*$}\idx\hfill&${}\equiv{}$&\string\hskip{} 0pt plus 1fill&h\\
               \llap{${}^*$}\idx\vfil&${}\equiv{}$&\string\vskip{} 0pt plus 1fil&v\\
               \llap{${}^*$}\idx\vfilneg&${}\equiv{}$&\string\vskip{} 0pt plus -1fil&v\\
               \llap{${}^*$}\idx\vfill&${}\equiv{}$&\string\vskip{} 0pt plus 1fill&v\\
               \llap{${}^*$}\idx\hss&${}\equiv{}$&\string\hskip{} 0pt plus1fil minus1fil&h\\
               \llap{${}^*$}\idx\vss&${}\equiv{}$&\string\vskip{} 0pt plus1fil minus1fil&v\\\hline
       \end{longtable}
\endgroup

\subsection{Les ressorts typographiques}
Int�ressons-nous aux ressorts-primitives �crits en gras dans le tableau pr�c�dent. Ces ressorts sont examin�s lorsque le paragraphe est compos�\idx*{paragraphe!composition}, c'est-�-dire lorsque \idx\par est ex�cut�. Il est donc inutile de modifier plusieurs fois ces ressorts dans le m�me paragraphe puisque seule la derni�re valeur sera prise en compte.

Cela implique en particulier que si un paragraphe\idx*{paragraphe!composition} est compos� dans un groupe (semi-simple ou non) dans lequel certains de ces ressorts sont modifi�s, il est n�cessaire de composer le paragraphe \emph{avant} de fermer le groupe. En �crivant \idx\par avant la fin du groupe, on s'assure que les valeurs des ressorts, modifi�es dans le groupe, seront bien prises en compte. En revanche, rejeter le \idx\par hors du groupe constitue une erreur, car les valeurs, restaur�es trop t�t � ce qu'elles �taient avant les modifications, rendent inutiles ces modifications internes au groupe.

\subsubsection{Ressort d'interligne}\label{ressort.interligne}\idx*[|(]{paragraphe!espace interligne}
Les boites contenant deux lignes cons�cutives d'un paragraphe ne sont g�n�ralement pas jointives. Le sch�ma ci-dessous illustre la situation : la distance entre les lignes de base des deux lignes cons�cutives est not�e $\Delta$ tandis que la distance entre les fronti�res des deux boites est not�e $\delta$.

\begin{centrage}
       \begin{tikzpicture}[inner sep=0pt,outer sep=0pt,minimum size=0pt,baseline,line width=0.4pt]
               \node[anchor=base west,draw,inner sep=-0.2pt]at(0,0)(boiteA){\vrule width0pt height.6cm depth.3cm \vrule height0pt width 3cm depth0pt };\draw[fill,black,overlay](boiteA.base west)circle(1pt);%
               \draw[gray,overlay]([xshift=-1cm]boiteA.base west)--([xshift=1cm]boiteA.base east)node[pos=1,anchor=south east,black,outer sep=1pt]{\tiny ligne de}node[pos=1,anchor=north east,black,outer sep=1pt]{\tiny base};
               \node[anchor=base west,draw,inner sep=-0.1pt]at(0,-1.2)(boiteB){\vrule width0pt height.5cm depth.2cm \vrule height0pt width 4cm depth0pt };
               \draw[fill,black,overlay](boiteB.base west)circle(1pt);%
               \draw[gray,overlay]([xshift=-1cm]boiteB.base west)--([xshift=1cm]boiteB.base east)node[pos=1,anchor=south east,black,outer sep=1pt]{\tiny ligne de}node[pos=1,anchor=north east,black,outer sep=1pt]{\tiny base};
               \draw[stealth-stealth]([xshift=-1.2cm]boiteA.base west)--([xshift=-1.2cm]boiteB.base west)node[pos=.5]{\footnotesize\llap{$\Delta$}\kern.75em };
               \draw[stealth-stealth]([xshift=-.2cm]boiteA.south west)--([xshift=-.2cm]boiteB.north west)node[pos=.5]{\footnotesize\llap{$\delta$}\kern.75em };
               \draw[stealth-stealth]([xshift=-.6cm]boiteA.south west)--([xshift=-.6cm]boiteA.base west)node[pos=.5]{\footnotesize\llap{$p$}\kern.75em };
               \draw[stealth-stealth]([xshift=-.6cm]boiteB.north west)--([xshift=-.6cm]boiteB.base west)node[pos=.5]{\footnotesize\llap{$h$}\kern.75em };
       \end{tikzpicture}
\end{centrage}

Plus g�n�ralement, si des boites sont empil�es les unes au-dessous des autres en mode vertical, un ressort-primitive vertical �\idx\baselineskip� est ins�r� entre elles. Ce ressort-primitive, appel� � \idx{ressort d'interligne} �, mesure l'espace ins�r�e entre les \emph{lignes de base} de ces boites.

Si la g�om�trie des boites (pr�cis�ment la quantit� $p+h$) fait que $\delta$ devient strictement inf�rieur � une certaine limite stock�e dans la dimension-primitive \idx\lineskiplimit, alors les deux boites sont empil�es verticalement de telle sorte que $\delta$ soit �gal au ressort-primitive \idx\lineskip. Math�matiquement, si

\[\Delta-(p+h)<\text{\ttfamily\char`\\lineskiplimit}\]\idx*\lineskiplimit
\noindent alors l'insertion de \idx\baselineskip entre les lignes de base est abandonn�e et le ressort-primitive \idx\lineskip est ins�r� \emph{entre les fronti�res des boites}.

Plain-\TeX{} effectue les initialisations suivantes :

\centrecode-\baselineskip=12pt    \lineskiplimit=0pt    \lineskip=1pt-

La macro \idx\nointerlineskip doit �tre appel�e en mode vertical et annule l'insertion du prochain \idx{ressort d'interligne} entre deux boites. Cette macro est � � un seul coup � et devra �tre appel�e � nouveau si plus tard, on souhaite annuler l'insertion du ressort d'interligne entre deux autres boites.

\showcode/Une premi�re ligne\par
\nointerlineskip% n'ins�re pas de ressort d'interligne ici�\idx*\nointerlineskip�
Un second paragraphe constitu� de plusieurs lignes.
Un second paragraphe constitu� de plusieurs lignes.
Un second paragraphe constitu� de plusieurs lignes.
\par% le ressort d'interligne sera ins�r� ici
Une derni�re ligne/

La macro \idx\offinterlineskip, d�sactive durablement l'insertion du ressort d'interligne. Il est prudent de l'utiliser dans un groupe afin d'en limiter la port�e.

\showcode/\begingroup
\offinterlineskip�\idx*\offinterlineskip�
La macro \litterate-\offinterlineskip-, en modifiant de fa�on appropri�e les trois�\idx*\offinterlineskip�*\litterate�
primitives \litterate-\baselineskip-, \litterate-\lineskip- et�\idx*\offinterlineskip�
\litterate-\lineskiplimit-, rend les boites cons�cutives jointives.�\idx*\baselineskip\idx*\lineskip\idx*\lineskiplimit�

On peut constater dans ces deux paragraphes o� \litterate-\offinterlineskip- a �t�\idx*\offinterlineskip�*\litterate�
appel�e, que les lignes sont plac�es verticalement au plus pr�s les unes des autres ce
qui rend la lecture tr�s p�nible et d�montre que le ressort d'interligne est une�\idx*{ressort d'interligne}�
n�cessit� typographique !\par
\endgroup
D�sactiver le ressort d'interligne ne se justifie que lorsque l'on doit composer�\idx*{ressort d'interligne}�
des boites contenant autre chose que du texte, sauf � vouloir des effets
typographiques sp�ciaux./

Les deux cas les plus courants o� la quantit� $p+h$ est �lev�e sont :

\begin{enumerate}
       \item la boite du haut est tr�s profonde et $p$ est grand (boite de type \idx\vtop);
       \item la boite du bas est tr�s haute et $h$ est grand (boite de type \idx\vbox).
\end{enumerate}

En voici l'illustration o� nous allons construire une boite du haut profonde et o� nous augmentons \idx\baselineskip afin de mieux visualiser le probl�me :

\showcode/\baselineskip=12pt
d�but \vtop{\hbox{ligne du haut ligne du haut ligne du haut}�\idx*\vtop�
\hbox{ligne du bas ligne du bas ligne du bas}
}
\par
Et la suite du texte suite du texte suite du texte/

On constate que l'espace vertical entre la � ligne du bas � de la \idx\vtop et la ligne suivante n'est pas \idx\baselineskip. En effet, \idx\lineskip a �t� ins�r� entre la fronti�re de la \idx\vtop et la premi�re ligne du paragraphe qui suit. Pour r�tablir un espacement correct, il faut mentir � \TeX{} sur la profondeur de la boite pr�c�dente. En mode vertical\idx*{mode!vertical}, la primitive \idx\prevdepth (qui mesure la longueur $p$ du sch�ma), ayant le type d'une dimension, contient la profondeur de la pr�c�dente boite plac�e dans la liste verticale. Apr�s �tre sorti de la \idx\vtop, cette valeur est �lev�e du fait de la profondeur de la boite. L'astuce consiste � sauvegarder $p$ dans une macro � la fin de la \idx\vtop de telle sorte que cette macro contienne la profondeur \emph{de la derni�re ligne} de la boite. Comme on ne peut acc�der � \idx\prevdepth qu'en mode vertical\idx*{mode!vertical}, il suffit donc apr�s le \idx\par d'assigner � \idx\prevdepth la valeur sauvegard�e.

\showcode/\baselineskip=12pt
d�but \vtop{\hbox{ligne du haut ligne du haut ligne du haut}�\idx*\vtop�
\hbox{ligne du bas ligne du bas ligne du bas}
\xdef\sprevdepth{\the\prevdepth}% sauvegarde la valeur de \prevdepth�\idx*\xdef�
}
\par\prevdepth=\sprevdepth\relax% ment sur la boite pr�c�dente�\idx*\prevdepth�
Et la suite du texte suite du texte suite du texte/\idx*[|)]{paragraphe!espace interligne}

\subsubsection{Les ressorts de paragraphe}\idx*[|(]{paragraphe!ressorts de paragraphe}
Avant de commencer un paragraphe, \TeX{} ajoute � la liste verticale l'espace mesur� par le ressort-primitive \idx\parskip (il n'est pas ajout� si la liste verticale est vide, c'est-�-dire au d�but d'une page ou d'une boite verticale). Ce ressort vient donc s'additionner au \idx{ressort d'interligne} vu pr�c�demment. Plain-\TeX{} proc�de � l'assignation suivante :

\centrecode-\parskip= 0pt plus 1pt-

Apr�s la fin de la derni�re ligne d'un paragraphe, \TeX{} ins�re horizontalement le ressort-primitive \idx\parfillskip. Plain-\TeX{} demande � ce que

\centrecode-\parfillskip= 0pt plus1fil-

\begingroup
\hbadness=10000 % pour �viter une avertissement de boite insuffisemment remplie
\parfillskip=0pt\relax
\noindent ce qui signifie qu'un ressort d'�tirement infini est ins�r� en fin de paragraphe. L'effet d'un tel ressort est de � pousser � le texte de la derni�re ligne de fa�on � ce qu'il ne se justifie pas. On peut bien s�r modifier ce ressort pour obtenir des effets typographiques comme dans ce paragraphe o� ce ressort a �t� rendu nul sans �tirement afin que la derni�re ligne soit justifi�e. Cet effet doit �tre utilis� avec parcimonie, car les espaces intermots de cette derni�re ligne, beaucoup trop larges ici, d�montrent que cet effet peut parfois �tre tr�s inesth�tique.
\par
\endgroup
\medbreak

Afin de bien voir la modification de la composition du paragraphe que cela entraine, voici le paragraphe pr�c�dent avec un ressort de fin de paragraphe ayant sa valeur par d�faut :\smallbreak

\noindent ce qui signifie qu'un ressort d'�tirement infini est ins�r� en fin de paragraphe. L'effet d'un tel ressort est de � pousser � le texte de la derni�re ligne de fa�on � ce qu'il ne se justifie pas. On peut bien s�r modifier ce ressort pour obtenir des effets typographiques comme dans ce paragraphe o� ce ressort a �t� rendu nul sans �tirement afin que la derni�re ligne soit justifi�e. Cet effet doit �tre utilis� avec parcimonie, car les espaces intermots de cette derni�re ligne, beaucoup trop larges ici, d�montrent que cet effet peut parfois �tre tr�s inesth�tique.

\subsubsection{Ressorts d'extr�mit�s de ligne}
Les ressorts \idx\leftskip et \idx\rightskip sont ins�r�s avant et apr�s le contenu de chaque ligne (\idx\rightskip est ajout� apr�s \idx\parfillskip � la derni�re ligne du paragraphe). Lorsqu'ils sont �gaux � \verb|0pt| comme c'est le cas par d�faut, le d�but et la fin de la ligne co�ncident avec les limites de la zone de texte et le texte est dit � justifi� � : ce sont les espaces entre les mots qui s'ajustent pour permettre cet effet typographique. La modification de ces ressorts d'extr�mit�s de ligne permet des compositions qui contrarient cette justification.

Ainsi, donner une composante infinie � ces ressorts revient � les faire � pousser � avec une force infinie de telle sorte que les espaces entre les mots seront contraints � prendre leur dimension \emph{naturelle} ce qui cassera la justification. Il est cependant plus judicieux de donner comme �tirement une composante \emph{finie} de telle sorte que celle-ci ne contraigne pas les espaces intermots. Il est utile de savoir qu'une composante \emph{infinie} des ressorts d'extr�mit� de ligne d�courage \TeX{} d'effectuer une seconde passe lors de la composition du paragraphe. Seule la premi�re passe est donc faite et les coupures de mots, envisag�es � la seconde passe, ne seront donc jamais faites (lire page~\pageref{provoquer.toutes.les.coupures}).

On voit que les ressorts d'extr�mit�s de ligne entretiennent un rapport avec les espaces intermots dont il est temps de parler. Chaque police poss�de des registres internes d�finissant la largeur naturelle de l'espace intermot, son possible �tirement et sa possible compression (lire page~\pageref{espace.dimensions.fonte}). Le ressort-primitive \idx\spaceskip permet, lorsqu'il re�oit une assignation, d'�craser localement le contenu des registres de la police concernant les dimensions de l'espace intermot. Il est donc possible de supprimer la composante �tirable de l'espace intermot afin que des espaces intermots trop longs et disgracieux soient �vit�s dans une composition non justifi�e.
\grandsaut

Les effets typographiques les plus courants obtenus � l'aide des ressorts d'extr�mit� de ligne sont :

\begin{itemize}
       \item composition au fer � gauche en donnant une composante �tirable finie (par exemple 2 ou 3 \verb|em|) � \idx\rightskip et en laissant \idx\leftskip nul;
       \item composition au fer � droite en inversant les r�les des deux ressorts dans la man\oe uvre d�crite au point pr�c�dent;
       \item centrage du contenu des lignes en donnant la \emph{m�me} composante �tirable aux deux ressorts. Cette composante doit ici �tre assez grande pour permettre le centrage de lignes tr�s courtes. Le choix de \verb|1000pt| est fait par plain-\TeX{} tandis que \LaTeX{} fait le choix de \texttt{0pt plus 1fil} pour sa macro \idx\centering. On peut �galement choisir \verb|0.5|\idx\hsize o� \idx\hsize est la dimension-primitive qui contient la largeur de composition. Enfin, pour que la derni�re ligne soit centr�e, il faut �galement annuler \idx\parfillskip qui sinon, deviendrait pr�pond�rant par rapport � \idx\leftskip et \idx\rightskip.
\end{itemize}

Voici un exemple de m�thode pour centrer deux paragraphes\idx*{paragraphe!centrage} entiers :

\showcode/\def\dummytext{Voici un texte qui ne rev�t aucune importance
       et dont le seul but est de meubler artificiellement un paragraphe. }
\begingroup% � l'int�rieur d'un groupe,�\idx*\begingroup�
       \leftskip=0pt plus 0.5\hsize\relax�\idx*\leftskip\idx*\hsize�
       \rightskip=\leftskip\relax % modifier les ressort d'extr�mit�s�\idx*\rightskip\idx*\leftskip�
       \spaceskip=0.3em plus 0.05em\relax% dimension de l'espace intermot�\idx*\spaceskip�
       \parfillskip=0pt \relax% annuler le ressort de fin de paragraphe�\idx*\parfillskip�
       \dummytext\dummytext\dummytext% corps du paragraphe
       \par% compose la paragraphe courant
       Juste une phrase%
       \par% compose la paragraphe courant
\endgroup% avant de sortir du groupe�\idx*\endgroup�/

En suivant cette m�thode, il est facile de construire une macro �\narrowtext qui compose le paragraphe pr�c�dent et qui diminue d�sormais la largeur de composition de 20\% de la largeur totale\idx*{paragraphe!diminuer la largeur}, sachant que cette largeur est contenue dans la dimension-primitive \idx\hsize. Le � bloc � de composition ainsi constitu� devra �tre centr� par rapport aux fronti�res de la zone de texte. Il faut pour cela augmenter (via la primitive \idx\advance) chacun des deux ressorts d'extr�mit�s de ligne de \verb|.1\hsize|. La macro \verb|\endnarrowtext| signera la fin de la composition en largeur diminu�e; elle composera le paragraphe en cours avec \idx\par et fermera le groupe semi-simple ouvert par �\narrowtext.

\showcode/\def\narrowtext{%��*\narrowtext�
       \par
       \begingroup
               \advance\leftskip 0.1\hsize�\idx*\advance\idx*\leftskip�
               \advance\rightskip 0.1\hsize�\idx*\advance\idx*\rightskip�
}
\def\endnarrowtext{\par\endgroup}
\def\dummytext{Ceci est un texte sans
importance destin� � meubler un paragraphe. }

\dummytext\dummytext\dummytext
\narrowtext
       \dummytext\dummytext\dummytext
\narrowtext
               \dummytext\dummytext\dummytext
\endnarrowtext
       \dummytext\dummytext\dummytext
\endnarrowtext/

Comme aucune des macros �\narrowtext ou \verb|\endnarrowtext| n'admet d'argument, il n'y a aucun risque de mettre entre elles un contenu tr�s long qui aurait pu inutilement surcharger la m�moire de \TeX{} s'il avait �t� maladroitement incorpor� dans un argument. L'autre avantage est que la lecture d'arguments est assortie du gel des catcodes qui n'existe pas ici.\idx*[|)]{paragraphe!ressorts de paragraphe}

\subsection{Ressorts pr�d�finis}
Les ressorts-primitives modifiables --~ceux qui �taient pr�c�d�s d'une �toile dans le tableau de la page~\pageref{tableau.ressort}~-- se comportent exactement comme s'ils �taient des macros d�finies avec \idx\newskip. La seule diff�rence est que leur valeur est fig�e. On remarque que \idx\hfil et \idx\vfil sont compens�s (c'est-�-dire annul�s) par \idx\hfilneg et \idx\vfilneg.

Les ressorts \idx\hss et \idx\vss sont eux encore plus curieux puisque, de dimension nulle, ils peuvent s'�tirer ou se comprimer infiniment. Nous verrons leur int�r�t plus loin.

Voici comment nous pouvons utiliser \idx\hfill pour composer au fer � droite, au fer � gauche, centrer une ligne ou bien encore, r�guli�rement espacer zones de texte sur une ligne :

\showcode/a) \hfill Composition au fer � droite\par
b) Composition au fer � gauche\hfill\kern0pt\par
c) \hfill Centrage\hfill\kern0pt\par
d) Des \hfill mots\hfill r�guli�rement\hfill espac�s/

Comment se justifie la pr�sence de ces � \idx\kern\verb|0pt|� apr�s les \idx\hfill en \idx{fin de ligne} ? Tout vient de la r�gle pr�c�dente qui stipule qu'un ressort qui se situe juste avant la fin d'un paragraphe (autrement dit juste avant \idx\par) est \emph{ignor�}. Ce \verb|\kern0pt| n'a d'autre but que de mettre quelque chose (on appelle cela un n\oe ud) entre le ressort et \idx\par. Bien �videmment, la dimension de ce n\oe ud doit �tre nulle afin que son encombrement ne fausse pas la largeur des �l�ments pris en compte. Au lieu d'�crire \verb|\kern0pt|, il est �galement courant d'employer la macro \idx\null d�finie par plain-\TeX{} dont le texte de remplacement est une boite horizontale vide, c'est-�-dire \idx\hbox\verb|{}|\idx*[|)]{registre!ressort}\idx*[|)]{dimension �tirable (ressort)}\idx*[|)]{dimension}.

\section{Les boites}\label{boites}\idx*[|(]{boite}
Dans le monde de \TeX{}, presque tout ce qui concerne la composition est li� aux boites. Les dimensions sont notamment utilis�es pour mesurer les caract�ristiques g�om�triques de ces boites. Les ressorts eux, sont charg�s de remplir des zones dans ces boites.

Avant de commencer, il est important de comprendre qu'une boite re�oit du code source transmis sous la forme d'un argument, mais prend en compte le r�sultat typographique de ce code \emph{une fois qu'il a �t� compos�}. Les assignations sont mises � part pour �tre ex�cut�s lorsque la boite est affich�e. Ainsi, mettre quelque chose dans une boite implique donc au pr�alable le travail complet de composition.

\subsection{Fabriquer des boites}
Si \TeX{}, de par son fonctionnement lors de la composition, fabrique automatiquement des boites pour les placer sur la page, des primitives permettent � l'utilisateur de fabriquer ses propres boites avec la possibilit� d'y mettre un contenu arbitraire.

\begin{regle}
       \relax\TeX{} dispose de trois primitives pour enfermer un mat�riel dans une boite :

       \begin{itemize}
               \item \idx\hbox\verb|{<code>}| construit une boite \emph{horizontale} contenant du mat�riel (qui est le r�sultat de la composition du \verb|<code>|) dispos� en mode horizontal\idx*{mode!horizontal} et compatible avec ce mode;
               \item \idx\vbox\verb|{<code>}| et \idx\vtop\verb|{<code>}| b�tissent des boites \emph{verticales}, susceptibles donc de recevoir du mat�riel dispos� en mode vertical\idx*{mode!vertical} et compatible avec ce mode.
       \end{itemize}

       Dans les trois cas, l'int�rieur d'une boite tient lieu de groupe, c'est-�-dire que les assignations faites dans le \verb|<code>| restent locales � la boite.

       Le \verb|<code>| n'est pas lu en une fois comme s'il �tait l'argument d'une macro; il est lu \emph{au fur et � mesure} que la boite se remplit et donc au fil de cette lecture, des changements de catcode sont permis.

       Une boite ainsi construite peut �tre :

       \begin{itemize}
               \item affich�e lorsque \idx\hbox, \idx\vbox ou \idx\vtop sont plac�s dans le flux d'entr�e de \TeX. Dans ce cas, la boite est ajout�e � la liste en cours selon le mode dans lequel \TeX{} travaille � ce moment (\idx*{boite!mode}horizontal\idx*{mode!horizontal} ou vertical\idx*{mode!vertical}). Il est important de noter que ni \idx\hbox ni \idx\vbox ou \idx\vtop ne provoquent de changement de mode, m�me si � l'int�rieur de ces boites, un mode �interne�\idx*{mode!interne} est impos�;
               \item stock�e dans un registre de boite (voir la section suivante).
       \end{itemize}
\end{regle}

Le code ci-dessous d�montre que les boites s'affichent selon le mode en cours :

\showcode/a% le caract�re "a" fait passer en mode horizontal�\idx*{mode!horizontal}�
\hbox{b}c\hbox{d}% les \hbox sont ajout�es en mode horizontal�\idx*{mode!horizontal}�
\medbreak
..� comparer avec...
\medbreak
a \par% \par fait passer en mode vertical�\idx*{mode!vertical}�
\hbox{b}% \hbox est ajout�e � la liste verticale
c% "c" fait passer en mode horizontal�\idx*{mode!horizontal}�
\hbox{d}% la \hbox est ajout�e en mode horizontal/

Il est important de se souvenir de cette r�gle lorsqu'on construit une macro dont le premier acte est d'afficher une boite construite avec une des trois primitives vues ci-dessus. En effet, on souhaite souvent placer d'autres choses � droite de cette boite (en mode horizontal donc). Si la macro est appel�e en mode vertical, le placement se fera \emph{en dessous}, et non pas \emph{apr�s} comme attendu. Pour se pr�munir de ce risque, il est \emph{tr�s sage} de mettre un \idx\leavevmode avant la boite pour quitter le mode vertical\idx*{mode!vertical}. Ce faisant, la boite sera compos�e en mode horizontal\idx*{mode!horizontal} et le comportement recherch� sera obtenu.
\grandsaut

Les boites construites avec \idx\vbox ou \idx\vtop empilent verticalement des �l�ments. Ces �l�ments sont susceptibles d'�tre mis dans une liste verticale car, � l'int�rieur de \idx\vbox ou \idx\vtop, on est dans le mode vertical (plus exactement en mode vertical \emph{interne}\idx*{mode!vertical interne}). Ce sont par exemple des paragraphes (qui ont une largeur �gale � \idx\hsize), des boites form�es avec une des trois primitives, des ressorts verticaux ins�r�s avec \idx\vskip, des r�glures (que nous verrons un peu plus loin), etc.

Autant la largeur d'une \idx\hbox est clairement la largeur du mat�riel que l'on y a mis, autant celle d'une \idx\vbox ou \idx\vtop est moins �vidente; La largeur d'une boite verticale est celle de l'�l�ment empil� verticalement qui a la plus grande largeur. Mais attention, si on �crit  �\verb|\vbox{foobar}|� ou �\verb|\vtop{foobar}|�, \TeX{} composera un paragraphe pour ce seul mot et mettra cet �l�ment dans la boite. Or, la largeur des paragraphes est �gale � la dimension-primitive \idx\hsize qui, dans le mode vertical principal, contient la largeur de la zone de texte. L'int�rieur d'une boite jouant le r�le de groupe, on peut certes modifier \idx\hsize dans une boite verticale pour imposer aux paragraphes une largeur choisie. Sans cette man\oe uvre pour modifier \idx\hsize, la largeur de la boite sera la m�me que celles des paragraphes de la page, ce qui est peut-�tre un peu surdimensionn� pour un paragraphe aussi court que �foobar� ! Au contraire, si l'on �crit �\verb|\vbox{\hbox{foobar}}|� ou �\verb|\vtop{\hbox{foobar}}|�, l'�l�ment qu'est la \idx\hbox sera ins�r� (en mode vertical\idx*{mode!vertical}) et au final, la boite verticale aura la largeur de cet �l�ment, c'est-�-dire la largeur du mot � foobar �.

\begin{regle}
Les primitives \idx\vbox et \idx\vtop d�finissent des boites dans lesquelles des �l�ments sont empil�s verticalement.

La diff�rence entre \idx\vbox et \idx\vtop r�side dans le \idx{point de r�f�rence} de la boite finale. Dans les deux cas, les �l�ments sont empil�s verticalement, le premier �tant en haut et le dernier en bas. Avec \idx\vbox, le point de r�f�rence de la boite est le point de r�f�rence du \emph{dernier} �l�ment (celui du bas) alors qu'avec \idx\vtop, son point de r�f�rence est celui du \emph{premier} �l�ment (celui du haut).
\end{regle}

Le \idx{point de r�f�rence} d'une boite �tant sur la \idx{ligne de base}, on comprend donc que \idx\vbox construit des empilements ayant des �l�ments au-dessus de cette ligne et donc produit en g�n�ral des boites de grande hauteur et faible profondeur. � l'oppos�, \idx\vtop produit des empilements ayant des �l�ments sous cette \idx{ligne de base} et donc des boites de petite hauteur et grande profondeur.
\grandsaut

Dans l'exemple ci-dessous, on met dans une \idx\vbox et une \idx\vtop des �l�ments dont la largeur est contr�l� puisque ce sont des \idx\hbox. On peut observer, gr�ce aux points qui repr�sentent approximativement la \idx{ligne de base} la diff�rence fondamentale entre une \idx\vbox et une \idx\vtop :

\showcode/Ligne de base : .........%
\vbox{\hbox{ligne du haut}\hbox{ligne du milieu}\hbox{ligne du bas}}%�\idx*\vbox�
........%
\vtop{\hbox{ligne du haut}\hbox{ligne du milieu}\hbox{ligne du bas}}.........�\idx*\vtop�/

Voici ce qui se passe en dessinant les boites et leur \idx{point de r�f�rence} :

\begin{centrage}
\footnotesize
\leavevmode\setbox0=\hbox{ligne du milieu}
Ligne de base.........%
\drawbox{\vbox{\raggedright\hsize\wd0 \drawbox{ligne du haut}\par\drawbox{ligne du milieu}\par\drawbox{ligne du bas}}}%
........%
\drawbox{\vtop{\raggedright\hsize\wd0 \drawbox{ligne du haut}\par\drawbox{ligne du milieu}\par\drawbox{ligne du bas}}}%
........%
\end{centrage}

Nous allons maintenant faire de m�me avec un �l�ment dont la largeur n'est pas contr�l�e, c'est-�-dire un paragraphe entier compos� de deux phrases identiques contenues dans la macro \verb|\dummytext|. Afin que les deux boites tiennent horizontalement dans l'espace qui leur est r�serv�, la largeur des boites verticales sera impos�e par \idx\hsize � \numprint[cm]4 :

\showcode/\def\dummytext{Bla, bla, bla, un texte sans importance. }
Ligne de base.........%
\vbox{\hsize=4cm \dummytext\dummytext}%�\idx*\vbox�
........%
\vtop{\hsize=4cm \dummytext\dummytext}.........�\idx*\vtop�/

\subsection{Registres de boite}\idx*[|(]{boite!registre}
Une boite simplement affich�e avec \idx\hbox, \idx\vbox ou \idx\vtop ne permet pas de travailler sur cette boite. En revanche, une boite \emph{stock�e} dans un registre ouvre d'autres perspectives puisqu'elle est m�moris�e par \TeX. D�s lors, il devient possible d'effectuer des op�rations sur ces boites.

Avant de poursuivre, il encore une fois est important de clarifier le sens du mot � stockage �. Autant les macros et les registres de tokens stockent du \emph{code source tok�niz�} c'est-�-dire du mat�riau brut initial, autant les registres de boites stockent d'un c�t� le r�sultat typographique d'un \verb|<code>| une fois qu'il a �t� compos� et de l'autre les assignations faites dans ce \verb|<code>|. Le stockage par macro et par boite sont deux stockages oppos�s en ce sens que chacun effectue une sauvegarde � l'un des deux bouts de la chaine qui m�ne du code source � l'affichage final.
\grandsaut

Nous commen�ons � �tre familiers avec les registres puisque, hormis les macros, il en existe pratiquement pour chaque type de donn�e que manipule \TeX{} (tokens, entiers, dimensions, ressorts). Les boites ne font �videmment pas exception � la r�gle, m�me si la syntaxe des registres de boites est l�g�rement diff�rente de celle des autres registres. La raison incombe au fait que \TeX{} ne poss�de pas de primitive \verb|\boxdef| alors qu'il poss�de \idx\toksdef, \idx\countdef, \idx\dimendef et \idx\skipdef.

\begin{regle}
\relax\TeX{} dispose de 256 registres de boites (\numprint{32768} avec \idx\eTeX).

On demande � \TeX{} d'allouer un num�ro de registre de boite par l'interm�diaire de la macro \idx\newbox\verb|\<macro>| et ce faisant, l'assignation suivante est faite

\centrecode-\global\chardef\<macro>=<nombre>-

o� le \verb|<nombre>| est un num�ro de registre de boite libre.

Ce faisant, la \verb|\<macro>| devient �quivalente � \idx\char\verb|<nombre>|. Ainsi, \verb|\<macro>| produit le caract�re de code \verb|<nombre>|, mais lorsque \TeX{} s'attend � lire un nombre (comme c'est le cas lorsqu'il attend un num�ro de boite), \verb|\<macro>| est lue comme l'entier \verb|<nombre>|. Du point de vue de la m�canique interne, un \verb|<registre>| de boite est donc un \verb|<nombre>|.

On acc�de � la boite contenue dans un registre par \idx\box\verb|<registre>|.

Pour proc�der � l'assignation, on �crit\idx*{assignation!registre de boite}\idx*\setbox :

\centrecode-\setbox<registre>= <boite valide>-

\noindent o� une \verb|<boite valide>| est soit une boite contenue dans un registre et �crite sous la forme \idx\box\verb|<registre>|, soit une boite construite avec les primitives \idx\hbox, \idx\vbox ou \idx\vtop. Le signe \verb|=| et l'espace qui le suit sont facultatifs.

Pour afficher une boite stock�e dans un \verb|<registre>|, on �crit \idx\box\verb|<registre>|. La boite est affich�e selon le mode en cours (horizontal ou vertical) : le type de boite n'a pas d'influence sur le mode dans lequel elle est affich�e.

Lorsqu'on utilise la primitive \idx\box pour acc�der � la boite stock�e dans un registre, la boite contenue dans le registre est irr�m�diablement perdue et le registre devient vide, c'est-�-dire qu'il ne contient aucune boite. Si on souhaite conserver la boite dans le registre, on doit utiliser la primitive \idx\copy au lieu de \idx\box.
\end{regle}

\begin{regle}
Le test\tidx*{ifvoid}%

\centrecode-\ifvoid<registre><code vrai>\else<code faux>\fi-

se comporte comme les autres tests de \TeX. Il revoit \verb|<code vrai>| si le \verb|<registre>| de boite est vide (c'est-�-dire s'il ne contient aucune boite).
\end{regle}

Il est admis que la boite \no0\idx*{boite!\no0} est une boite � brouillon � qui peut �tre utilis�e ponctuellement si l'on ne veut pas mobiliser un nouveau registre de boite.
\grandsaut

L'exemple ci-dessous illustre ce que nous venons d'aborder. Nous allons tout d'abord allouer un nouveau registre \verb|\foobox| par \idx\newbox et nous y stockerons une boite horizontale contenant le mot � foobar �. Ensuite, nous allons utiliser le test \tidx{ifvoid} dans plusieurs cas de figure afin de montrer que le registre devient vide apr�s avoir ex�cut� la primitive \idx\box.

\showcode/\newbox\foobox�\idx*\newbox�
a) \setbox\foobox=\hbox{foobar}% registre non vide�\idx*\setbox�
  Le registre est \ifvoid\foobox vide\else non vide\fi\par
b) \setbox\foobox=\hbox{foobar}
  "\box\foobox" et le registre est \ifvoid\foobox vide\else non vide\fi\par
c) \setbox\foobox=\hbox{foobar}
  "\copy\foobox" et le registre est \ifvoid\foobox vide\else non vide\fi\par
d) \setbox\foobox=\hbox{}
  Le registre est \ifvoid\foobox vide\else non vide\fi�\tidx*{ifvoid}�/

On remarque que \idx\box vide le registre (cas b) tandis que \idx\copy le pr�serve (cas c). Il est �galement important de noter que le registre n'est pas vide (cas d) s'il contient une boite vide.
\grandsaut

Deux autres tests sur les registres de boite m�ritent d'�tre signal�s :

\begin{centrage}
\small\tidx{ifhbox}\verb|<registre>|\quad et\quad\tidx{ifvbox}\verb|<registre>|
\end{centrage}

\noindent sont vrais si le \verb|<registre>| contient respectivement une boite horizontale ou verticale.\idx*[|)]{boite!registre}

\subsection{Dimensions des boites}\idx*[|(]{boite!dimension}
\begin{regle}
Les dimensions d'une boite stock�e dans un \verb|<registre>| sont :
\begin{itemize}
       \item sa longueur horizontale, accessible par \idx\wd\verb|<registre>| ;
       \item sa hauteur, qui s'�tend au-dessus de la \idx{ligne de base}, accessible par \idx\ht{}\linebreak[1]\verb|<registre>| ;
       \item enfin, sa profondeur qui s'�tend au-dessous de la \idx{ligne de base} et qui est accessible par \idx\dp\verb|<registre>|.
\end{itemize}

Les primitives \idx\wd, \idx\ht et \verb|\dp| suivies d'un \verb|<registre>| se comportent comme des registres de dimension.
\end{regle}

\noindent Pour fixer les id�es, voici un sch�ma o� les \idx*{boite!englobante}boites englobantes, rectangles qui repr�sentent l'encombrement d'une boite tel qu'il est pris en compte par \TeX, sont trac�es et les trois dimensions sont �crites pour quatre lettres diff�rentes :\medbreak

\noindent\hskip0.1\linewidth\hbox to0pt{\dimenbox{g}\hss}\hskip0.5\linewidth\hbox to0pt{\dimenbox{o}\hss}\medbreak
\noindent\hskip0.1\linewidth\hbox to0pt{\dimenbox{P}\hss}\hskip0.5\linewidth\hbox to0pt{\dimenbox{\itshape f}\hss}\medbreak

On peut observer notamment avec la lettre �\textit{f}\kern1pt� que la boite englobante\idx*{boite!englobante} ne correspond pas � la plus petite boite qui contient les contours de la lettre. Pour d'�videntes raisons de typographie, il est \emph{n�cessaire} que certaines parties de la lettre �\textit{f}� d�passent de la boite englobante\idx*{boite!englobante} sinon, au lieu de �\textit{foo}�, nous aurions un horrible �\textit{f\kern1.65ptoo}� !

De plus, contrairement � ce que l'on pourrait croire, la profondeur de lettres comme �o� ou �P� n'est pas nulle ! Tr�s faible certes, mais pas nulle\ldots{} Le concepteur de la \idx{fonte} �Libertine� avec laquelle est �crit ce livre en a d�cid� ainsi.
\grandsaut

Passons � la pratique et mesurons maintenant les dimensions de boites construites successivement avec les trois primitives \idx\hbox, \idx\vbox et \idx\vtop. Les boites verticales seront des empilements de \idx\hbox, chacune contenant un mot de la phrase �Programmer est facile.�

\showcode/\newbox\foobox�\idx*\newbox�
\setbox\foobox=\hbox{Programmer est facile.}�\idx*\setbox�
<<\copy\foobox>>�\idx*\copy�
mesure \the\wd\foobox\ de long, \the\dp\foobox\ de profondeur et \the\ht\foobox\ de haut.�\idx*\the\idx*\wd\idx*\dp�
\medbreak�\idx*\medbreak�

\setbox\foobox=\vbox{\hbox{Programmer}\hbox{est}\hbox{facile.}}�\idx*\setbox�
<<\copy\foobox>>
mesure \the\wd\foobox\ de long, \the\dp\foobox\ de profondeur et \the\ht\foobox\ de haut.
\medbreak�\idx*\medbreak�

\setbox\foobox=\vtop{\hbox{Programmer}\hbox{est}\hbox{facile.}}�\idx*\setbox\idx*\vtop�
<<\copy\foobox>>
mesure \the\wd\foobox\ de long, \the\dp\foobox\ de profondeur et \the\ht\foobox\ de haut.�\idx*\the\idx*\wd\idx*\dp�/

La faible profondeur de la \idx\vbox provient une fois encore du design de la \idx{fonte} Libertine qui donne une faible profondeur � certaines lettres qui composent le mot du bas �facile�. La verticalit� \emph{totale} des boites verticales (c'est-�-dire la somme de leur hauteur et de leur profondeur) \idx\vbox et \idx\vtop est la m�me dans les deux cas.

\begin{exercice}
Programmer une macro �\vdim\verb|{<registre>}| qui calcule la verticalit� de la boite contenue dans le \verb|<registre>|.
\solution
Il suffit de donner � \idx\dimexpr l'addition de sa hauteur et sa profondeur :

\showcode/\def\vdim#1{\dimexpr\ht#1+\dp#1\relax}��*\vdim�
a) \setbox\foobox=\vbox{\hbox{Programmer}\hbox{est}\hbox{facile.}}�\idx*\setbox�
  Verticalit� de la \litterate-\vbox- = \the\vdim\foobox\par��*\litterate\idx*\the�
b) \setbox\foobox=\vtop{\hbox{Programmer}\hbox{est}\hbox{facile.}}�\idx*\setbox�
  Verticalit� de la \litterate-\vtop- = \the\vdim\foobox��*\litterate\idx*\the�/
\end{exercice}

\begin{exercice}
Inventer un proc�d� qui permette de compter combien de caract�res affichables contient un argument. On appellera la macro �\countallchar\verb|{<texte>}| et on supposera que le \verb|<texte>| est uniquement constitu� de caract�res affichables (catcodes 11 et 12) et d'espaces.
\solution
Au point o� nous en sommes, la solution la plus imm�diate est de mettre cet argument dans une boite \idx\hbox o� la \idx{fonte} sera � chasse fixe. Il suffit de mesurer cette boite, de mesurer un caract�re et d'effectuer la division entre les entiers contraints de ces deux dimensions pour afficher le nombre de caract�res. Ici, nous allons m�me afficher la division conduisant au r�sultat :

\showcode|\def\countallchar#1{%��*\countallchar�
       Il y a %
       \setbox0=\hbox{\tt#1}% met #1 dans la boite�\idx*\setbox�
       \edef\arglength{\number\wd0 }% stocke la largeur de la boite en sp�\idx*\number\idx*\wd\idx*{sp (unit�)}�
       \setbox0=\hbox{\tt A}% met "A" dans la boite�\idx*\setbox�
       \edef\charlength{\number\wd0 }% stocke la largeur d'un caract�re
       $\number\arglength/\charlength % affiche la division�\idx*\wd�
       =\number\numexpr\arglength/\charlength\relax$ % affiche le quotient�\idx*\wd�
       caract�res%
}
\countallchar{abcd efgh}\par
\countallchar{A5 xW5 64 a1}\par
\countallchar{affligeant}��*\countallchar�|

Une m�thode similaire peut �tre d�ploy�e pour compter combien de fois figure un caract�re affichable $\alpha$ dans un argument. L'id�e est de mesurer la boite contenant l'argument compos� en fonte � chasse fixe et stocker cette longueur dans $L$. Ensuite, le caract�re $\alpha$ est supprim� avec la macro �\substin et la man\oe uvre est r�p�t�e : $l$ est la nouvelle longueur. Le nombre d'occurrences de $\alpha$ est la diff�rence $L-l$ divis�e par la longueur de la boite contenant $\alpha$ :

\showcode|\catcode`@11
\def\countchar#1#2{%
               \setbox\z@\hbox{\tt#2}% met #2 dans boite 0�\idx*\setbox\idx*\tt �*\defactive\idx*\string\idx*\hbox\idx*\z@�
               \edef\len@a{\number\wd\z@}% mesure la boite�\idx*\wd�
               \setbox\z@\hbox{\tt\substin{#2}{#1}{}}% recommencer sans "#1"�\idx*\setbox�*\defactive�
               \edef\len@b{\number\wd\z@}% mesure la boite
               \setbox\z@\hbox{\tt A}% met "A" dans la boite�\idx*\setbox\idx*\string�
               \edef\charlength{\number\wd\z@}% stocke la largeur du caract�re
               \number\numexpr(\len@a-\len@b)/\charlength% et affiche le quotient
}
\catcode`@12
a) \countchar{a}{abracadabra}\qquad
b) \countchar{b}{zigzag}\qquad
c) \countchar{ }{a bc de f ghi j k }��*\countchar�|
\end{exercice}\idx*[|)]{boite!dimension}

\subsection{D�placer des boites}\idx*[|(]{boite!d�placement}
\TeX{} met � disposition des primitives pour d�placer des boites dans la direction que l'on veut (haut, bas, gauche, droite).

\begin{regle}
Les primitives \idx\lower ou \idx\raise doivent �tre suivies d'une \verb|<dimension>|, le tout devant pr�c�der une boite horizontale, qu'elle soit �crite par l'interm�diaire de \idx\hbox ou d'un registre. L'effet est d'abaisser pour \idx\lower ou d'�lever pour \idx\raise la boite de la \verb|<dimension>| sp�cifi�e.

Les primitives \idx\moveleft et \idx\moveright partagent la m�me syntaxe, mais agissent sur des boites \emph{verticales} en les d�pla�ant vers la gauche ou vers la droite.
\end{regle}

Voici comment on peut enfermer des mots dans une \idx\hbox et les �lever ou les abaisser d'une dimension arbitraire :

\showcode/Programmer \raise1ex\hbox{en} \lower1ex\hbox{\TeX} \lower2ex\hbox{est} facile.�\idx*\raise\idx*\lower\idx*\hbox�/

Il faut d'ailleurs noter que le logo �\TeX�, obtenu en ex�cutant la macro \index{TeX@\texttt{\char92 TeX}}\verb|\TeX|, est construit en utilisant \idx\lower pour abaisser la lettre �E� apr�s rebrouss� chemin vers la gauche � l'aide de \idx\kern. La lettre �X� est �galement d�plac�e vers la gauche avec un autre \idx\kern. Voici comment est d�finie la macro \index{TeX@\texttt{\char92 TeX}}\TeX{} par plain-\TeX :

\centrecode|\def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX}|
\grandsaut

Il peut sembler frustrant que l'on ne puisse pas � centrer � une boite contenant du mat�riel vertical par rapport � l'axe qu'est la \idx{ligne de base} puisque \idx\vbox et \idx\vtop empilent ce mat�riel respectivement au-dessus ou au-dessous de cette ligne. L'id�e serait d'abaisser ces boites avec \idx\lower de la dimension �gale �

\[\frac{\hbox{hauteur}-\hbox{profondeur}}2\]

\noindent �tant entendu que si cette quantit� est n�gative, abaisser d'une dimension n�gative revient � �lever la boite. En coulisses, cette m�thode nous contraint � mettre la boite dans un registre pour pouvoir la mesurer afin d'acc�der � sa hauteur et sa profondeur. La macro �\cbox va mettre en application cette m�thode et sera amen�e � recevoir du mat�riel vertical dans les m�mes conditions que \idx\vbox afin de centrer la boite par rapport � la \idx{ligne de base} :

\showcode|\def\cbox#1{%��*\cbox�
       \setbox0\vbox{#1}% met le contenu dans une \vbox�\idx*\setbox\idx*\vbox�
       \lower\dimexpr(\ht0-\dp0)/2\relax\box0 % l'abaisse�\idx*\lower\idx*\dimexpr\idx*\ht\idx*\dp\idx*\box�
}

.....\cbox{\hbox{$x^2$}}......\cbox{\hbox{foo}\hbox{et bar}}......%
\cbox{\hbox{Programmer}\hbox{en \TeX}\hbox{est facile}}.......��*\cbox�|

\TeX{} dispose de la primitive \idx\vcenter, qui fonctionne en mode math�matique\idx*{mode!math�matique}, dont l'argument est constitu� de mat�riel vertical (comme l'est celui de \idx\vbox ou \idx\vtop) et qui place la boite ainsi cr�� de telle sorte que ses fronti�res haute et basse soient �quidistantes de �l'axe math�matique�. Deux pr�cisions doivent �tre apport�es :

\begin{itemize}
       \item la primitive ne peut �tre appel�e qu'en mode math�matique\idx*{mode!math�matique}, mais le contenu de la boite n'h�rite pas de ce mode, c'est-�-dire qu'il sera compos� en mode texte, sauf si bien s�r, on demande explicitement � passer en mode math�matique\idx*{mode!math�matique} � l'int�rieur de la boite (les boites \idx\hbox, \idx\vbox et \idx\vtop partagent aussi cette propri�t�) ;
       \item l'axe math�matique \emph{n'est pas} � la m�me hauteur que la \idx{ligne de base}; il s'agit de deux axes diff�rents. L'axe math�matique est horizontal et se trouve approximativement � �quidistance des traits horizontaux du signe �$=$�. Il repr�sente l'axe de sym�trie horizontal de plusieurs signes math�matiques alors que la \idx{ligne de base} est approximativement tangente au bas des lettres qui n'ont pas de jambage comme on le voit dans l'�galit� ci-dessous :
       \begin{centrage}
               \begingroup\huge
               \setbox0\hbox{$\vcenter{}$}%
               \xdef\htmath{\the\ht0}%
               \endgroup
               \begin{tikzpicture}[inner sep=0pt,outer sep=0pt,minimum size=0pt,baseline,line width=0.2pt]
                       \node[anchor=base west](equation){\huge $a\kern.125em(b+c)=ab+ac$};
                       \draw[gray]([xshift=-2cm]equation.base west)--([xshift=0.2cm]equation.base east)node[pos=0,anchor=south west,outer sep=1pt,black]{\scriptsize ligne}node[pos=0,anchor=north west,outer sep=1pt,black]{\scriptsize de base};
                       \draw[gray]([xshift=-0.2cm,yshift=\htmath]equation.base west)--([xshift=2cm,yshift=\htmath,black]equation.base east)node[pos=1,anchor=south east,outer sep=1pt,black]{\scriptsize axe}node[pos=1,outer sep=1pt,anchor=north east,black]{\scriptsize math};
               \end{tikzpicture}
       \end{centrage}
\end{itemize}

Par cons�quent, une boite centr�e avec \idx\vcenter ne sera pas exactement � la m�me hauteur que la m�me boite centr�e avec la macro �\cbox vue pr�c�demment. La diff�rence se voit sans peine � l'\oe il nu dans cet exemple :

\showcode|......\cbox{\hbox{foo}\hbox{et bar}}......$\vcenter{\hbox{foo}\hbox{et bar}}$......�\idx*\vcenter�*\cbox�|\idx*[|)]{boite!d�placement}

\begin{exercice}
Inventer un proc�d� pour que la macro �\htmath affiche � quelle distance de la ligne de base se trouve l'axe math�matique.
\solution
Si une \idx\hbox contient une \idx\vcenter vide, la hauteur de la \idx\hbox sera pr�cis�ment la distance cherch�e.

\showcode/\def\htmath{\begingroup��*\htmath�
       \setbox0=\hbox{$\vcenter{}$}\the\ht0 �\idx*\setbox\idx*\vcenter\idx*\the\idx*\ht�
\endgroup
}
L'axe math�matique se trouve � \htmath{} de la ligne de base./
\end{exercice}

\subsection{Choisir la dimension d'une boite}\idx*[|(]{boite!dimension choisie}
\begin{regle}
On peut imposer une dimension aux boites en le sp�cifiant avec le mot-cl� �\idx*{boite!mot-cl� �to�}\verb|to|� suivi d'un espace optionnel puis d'une \verb|<dimension>|. Et donc, si l'on �crit

\centrecode-\hbox to 3cm{<contenu>}-

\noindent cela cr�era une boite horizontale de longueur \numprint[cm]{3}, quel que soit le \verb|<contenu>|. Si le contenu ne mesure pas \emph{exactement} \numprint[cm]{3} et ne contient aucun �l�ment �tirable, il y aura soit un d�bordement, soit un sous-remplissage de boite, chacun respectivement signal� par les messages d'avertissement\idx*{message d'avertissement} �\texttt{Overfull \string\hbox}� ou �\texttt{Underfull \string\hbox}� dans le \idx[!log]{fichier} \verb|log|. La m�me syntaxe s'applique pour \idx\vbox et \idx\vtop sauf que la dimension est impos�e dans le sens \emph{vertical}.

On peut �galement �crire le mot-cl� �\idx*{boite!mot-cl� �spread�}\verb|spread|� utilis� � la place de �\verb|to|� si l'on souhaite construire une boite dont la dimension finale sera sa dimension naturelle augment�e de la \verb|<dimension>|. Si cette dimension est n�gative, la boite cr��e aura une dimension inf�rieure � sa dimension naturelle.
\end{regle}

Voici un exemple qui montre comment une boite est affich�e avec sa largeur naturelle puis �tir�e de \verb|5pt| et \verb|10pt| gr�ce � un ressort \idx\hfil plac� entre les syllabes �\verb|foo|� et �\verb|bar|�:

\showcode/1) \hbox{foobar}\par�\idx*\hbox�
2) \hbox spread 5pt{foo\hfil bar}\par
3) \hbox spread10pt{foo\hfil bar}/

\Qu e ce soit via �\verb|to|� ou �\verb|spread|�, il est n�cessaire que contenu de la boite ait un ou plusieurs ressorts. Ils devront avoir des composantes �tirables convenablement choisies pour qu'en s'�tirant ou en se comprimant, ils puissent compenser l'exc�s ou le manque de place pour le contenu. Un des ressorts les plus utilis�s dans ce cas est \idx\hss pour les boites horizontales et \idx\vss pour les boites verticales. Rappelons qu'ils ont une longueur nulle et peuvent s'�tirer ou se comprimer infiniment.
\grandsaut

On peut facilement cr�er des macros qui affichent du texte \emph{en surimpression} soit � droite, soit � gauche de la position courante. Ces deux macros, \idx\rlap et \idx\llap, dont le nom signifie � right overlap � (surimpression vers la droite) ou � left overlap � (surimpression vers la gauche) sont ainsi d�finies dans le \idx[!plain-\TeX]{format} plain-\TeX :

\centrecode-\def\rlap#1{\hbox to\z@{#1\hss}}�\idx*\z@�
\def\llap#1{\hbox to\z@{\hss#1}}-

Examinons tout d'abord \idx\rlap. Son argument \verb|#1| est mis dans une boite horizontale de longueur nulle (\idx\z@ repr�sente la dimension \verb|0pt|). Un sur-remplissage de la boite semble in�vitable, car le contenu \verb|#1| prend une certaine place horizontale. C'est l� que le ressort \idx\hss plac� en fin de boite va intervenir : pour satisfaire la longueur de la boite nulle, il va se comprimer pour atteindre une longueur n�gative exactement �gale � l'oppos� de la longueur de l'argument \verb|#1|. La somme des longueurs de \verb|#1| et de \idx\hss satisfait bien la dimension nulle impos�e.

\begin{centrage}
       \footnotesize
       \begin{tikzpicture}
               \useasboundingbox (-3,-2) rectangle (4,1);
               \draw[line width=1pt](0,-2)--(0,0)node[above,align=center,text width=1.5cm]{Position courante};
               \node[draw,anchor=mid west,align=center,text width=3cm,inner sep=0pt,outer sep=0pt](arg1)at(0,-.5){\vrule height2.5ex depth1.5ex width0pt Argument \ttfamily \#1}node[anchor=mid west] at(4,-.5){�tape \no1};
               \draw [-stealth](.15,-1.5)--(0,-1.5);
               \draw[decorate,decoration={zigzag,segment length=0.3cm,amplitude=1mm}] (.15,-1.5)--(3cm,-1.5)
                       node[below,pos=.5,yshift=-.1cm]{ressort \ttfamily\string\hss}
                       node[anchor=mid west] at(4,-1.5){�tape \no2};
       \end{tikzpicture}
\end{centrage}

Son homologue \idx\llap fonctionne de la m�me fa�on sauf que le ressort \idx\hss est plac� en d�but de boite : il va donc se comprimer en premier ce qui se traduit � l'affichage par un recul vers la gauche de la longueur de \verb|#1|. Ensuite, \verb|#1| est compos� et rattrape exactement la longueur n�gative de \idx\hss.

\begin{centrage}
       \footnotesize
       \begin{tikzpicture}
               \useasboundingbox (-3,-2) rectangle (4,1.5);
               \draw[line width=1pt](0,-2)--(0,0.5)node[above,align=center,text
width=1.5cm]{Position courante};
               \node[draw,anchor=mid east,align=center,text width=3cm,inner sep=0pt,outer sep=0pt](arg1)at(0,-1.5){\vrule height2.5ex depth1.5ex width0pt Argument\ttfamily  \#1}node[anchor=mid west] at(.5,-1.5){�tape \no2};
               \draw [-stealth](-2.85,-.5)--(-3,-.5);
               \draw[decorate,decoration={zigzag,segment length=0.3cm,amplitude=1mm}] (-2.85cm,-0.5)--(0,-0.5)
                       node[above,pos=.5,yshift=.1cm]{ressort \ttfamily\string\hss}
                       node[anchor=mid west] at(.5,-0.5){�tape \no1};
       \end{tikzpicture}
\end{centrage}

L'exemple ci-dessous montre comment ces deux macros peuvent utilis�es pour �crire soit � gauche, soit � droite de la position courante en surimpression. Dans les deux cas, le caract�re �|� est utilis� pour symboliser la position courante lorsque \TeX{} rencontre ces deux macros :

\showcode=foobar|\rlap{/////}123456\qquad foobar|\llap{/////}123456�\idx*\rlap\idx*\llap�=

Il est curieux que \idx*{Knuth Donald}D.~\textsc{Knuth} n'ait pas impl�ment� la macro �\clap qui permettrait de centrer le contenu de son argument sur la position courante sans que l'encombrement horizontal ne soit pris en compte :

\centrecode-\def\clap#1{\hbox to0pt{\hss#1\hss}}-�*\clap

Bien s�r, le fonctionnement de cette macro est en tout point semblable � \idx\rlap et \idx\llap sauf que les deux ressorts se compriment de fa�on identique ce qui donne un centrage du contenu par rapport � la position courante:

\begin{centrage}
       \footnotesize
       \begin{tikzpicture}
               \useasboundingbox (-3,-3) rectangle (4,1);
               \draw[line width=1pt](0,-3)--(0,0)node[above,align=center,text width=1.5cm]{Position courante};
               \draw [-stealth](-1.35,-.5)--(-1.5,-.5);
               \draw[decorate,decoration={zigzag,segment length=0.3cm,amplitude=1mm}] (-1.35cm,-0.5)--(0,-0.5)
                       node[below,pos=.5,yshift=-.1cm]{\ttfamily\string\hss}
                       node[anchor=mid west] at(2,-0.5){�tape \no1};
               \node[draw,align=center,text width=3cm,inner sep=0pt,outer sep=0pt](arg1)at(0,-1.5){\vrule height2.5ex depth1.5ex width0pt Argument \ttfamily\#1}node[anchor=mid west] at(2,-1.5){�tape \no2};
               \draw [-stealth](0.15,-2.5)--(0,-2.5);
               \draw[decorate,decoration={zigzag,segment length=0.3cm,amplitude=1mm}] (1.5,-2.5)--(.15,-2.5)
                       node[below,pos=.5,yshift=-.1cm]{\ttfamily\string\hss}
                       node[anchor=mid west] at(2,-2.5){�tape \no3};
       \end{tikzpicture}
\end{centrage}

Des effets d'empilement peuvent �tre cr��s avec les macros \idx\raise et \idx\lower qui d�placent verticalement la prochaine boite horizontale d'une dimension choisie :

\showcode/\def\clap#1{\hbox to0pt{\hss#1\hss}}�\idx*\hss�*\clap�
a) avant la macro|\clap{SURIMPRESSION}apr�s la macro\medbreak
b) avant la macro|\raise2.5ex\clap{Au-dessus}\lower2.5ex\clap{Au-dessous}%
  apr�s la macro\medbreak�\idx*\raise\idx*\lower�*\clap�
c) avant la macro|\raise2.5ex\llap{Au-dessus avant}\lower2.5ex\rlap{Au-dessous apr�s}%
  apr�s la macro�\idx*\rlap\idx*\llap�/\idx*[|)]{boite!dimension choisie}

\newpage% TODO : pour ne pas que le titre de la sous section soit orphelin en bas de page
\subsection{Redimensionner une boite}\idx*[|(]{boite!redimensionnement}
\begin{regle}
Une fois qu'une boite est stock�e dans un \verb|<registre>|, il est possible de modifier une ou plusieurs de ses dimensions. Il suffit d'�crire

\begin{centrage}
\small$\left.\vcenter{\ttfamily\hbox{\string\wd}\hbox{\string\ht}\hbox{\string\dp}}\right\}$\verb|<registre>= <dimension>|\idx*\wd\idx*\ht\idx*\dp
\end{centrage}

\noindent pour que la largeur, hauteur ou profondeur de la boite prenne la dimension indiqu�e, ind�pendamment de ce qu'est le contenu de la boite. Ces assignations sont toujours \emph{globales}\idx*{assignation!toujours globale}. En proc�dant de cette fa�on, le contenu reste intact, mais \TeX{} est tromp� et voit d�sormais la boite avec les nouvelles dimensions.
\end{regle}

Un peu � la mani�re de \idx\rlap, il devient ainsi possible de superposer une boite au texte qui la suit :

\showcode |\setbox0=\hbox{\tt//////////}�\idx*\tt\idx*\setbox�
\wd0=0pt % fait croire � TeX que la larguer de la boite est nulle�\idx*\wd�
Voici \copy0 du texte partiellement barr�...�\idx*\copy�|

Est-il possible de redonner au contenu d'une boite ainsi modifi�e une nouvelle virginit� quant � ses dimensions, et faire en sorte que ce contenu occupe � nouveau ses dimensions naturelles ?

\begin{regle}
Si un \verb|<registre>| de boite contient une boite horizontale ou verticale, il est possible d'extraire le contenu de la boite avec \idx\unhbox\verb|<registre>| ou \idx\unvbox\verb|<registre>|. La liste horizontale ou verticale contenue dans la boite est alors ajout�e � la liste courante en cours. Apr�s cette op�ration, le registre de boite devient vide, c'est � dire positif au sens de \tidx{ifvoid}.

Pour ne pas vider le registre de boite, il faut employer \idx\unhcopy ou \idx\unvcopy.
\end{regle}

L'important � retenir de cette r�gle est que la liste ainsi extraite retrouve ses dimensions naturelles, m�me si les dimensions de la boite avaient �t� modifi�es apr�s coup.

\showcode/\def\printdim{largeur=\the\wd0 \qquad hauteur=\the\ht0 \qquad profondeur = \the\dp0 }�\idx*\the\idx*\wd\idx*\ht�
\setbox0=\hbox{Programmer en \TeX{} est facile}�\idx*\setbox�
a) \printdim\par
b) \wd0=0pt \ht0=0pt \dp0=0pt% rend toutes le dimensions nulles�\idx*\wd\idx*\ht\idx*\dp�
  \printdim\par
c) \setbox0=\hbox{\unhbox0 }% reprend les dimensions d'origine�\idx*\hbox\idx*\unhbox\idx*\setbox�
  \printdim/

Le point essentiel est que

\centrecode-\setbox<registre>=\hbox{\unhbox<registre>}-\idx*\unhbox

\noindent redonne au \verb|<registre>| de boite les dimensions naturelles de la boite qu'il contient. La m�thode donn�e pour une boite horizontale est �galement valable pour une boite verticale en rempla�ant \idx\hbox par \idx\vbox ou \idx\vtop et \idx\unhbox par \idx\unvbox.\idx*[|)]{boite!redimensionnement}

\subsection{Tester si un registre de boite est vide}\label{tester.boite.vide}\idx*[|(]{boite!registre!vide}
Nous avons vu que le test \tidx{ifvoid}\verb|<registre>| est vrai si le registre de boite est vide. Il est tout de m�me tr�s important d'insister sur la diff�rence entre un registre vide (c'est � dire ne contenant aucune boite) et un registre contenant une boite vide.

Voici un exemple qui illustre le fait que si un registre contient une boite vide, il n'est pas vide !

\showcode/\setbox0=\hbox{}% le registre 0 contient une boite vide�\idx*\setbox�
Le registre \ifvoid0 est vide\else n'est pas vide\fi�\tidx*{ifvoid}�/

D�s lors se pose la question : � comment tester si un registre de boite est vide ?� La r�ponse d�pend de ce qu'on entend par � vide �. Le parall�le devient �vident avec un argument de macro qui n'�tait pas � vide � s'il contenait une macro vide telle que \idx\empty (voir page~\pageref{argument.vide}). Pour r�pondre � la question � comment tester si un registre de boite est vide �, nous allons construire un test purement d�veloppable �\ifzerodimbox de syntaxe

\centrecode-\ifzerodimbox{<nombre>}{<code vrai>}{<code faux>}-

qui renvoie \verb|<code vrai>| si le registre est vide ou s'il contient une boite dont toutes les dimensions sont nulles, et faux dans tous les autres cas.

\showcode/\catcode`\@11
\def\ifzerodimbox#1{% #1=registre de boite��*\ifzerodimbox�
% revoie vrai si le registre est vide ou contient une boite de dimensions nulles
       \csname% former la macro "\firstoftwo" ou "\secondoftwo"
       \ifvoid#1first%% si le registre est vide "first"�\tidx*{ifvoid}�
       \else% sinon
               \ifdim\wd#1=\z@% si la largeur�\idx*\wd\idx*\z@�
                       \ifdim\ht#1=\z@% la hauteur�\idx*\ht�
                               \ifdim\dp#1=\z@ first% et la profondeur=0pt, "first"�\idx*\dp\idx*\z@�
                               \else second% dans les autres cas "second"
                               \fi
                       \else second%
                       \fi
               \else second%
               \fi
       \fi
       oftwo% compl�ter avec "oftwo"
       \endcsname
}
\catcode`\@12
a) \setbox0=\hbox{}\ifzerodimbox0{vrai}{faux} (et \ifvoid0 void\else non void\fi)\par�\idx*\setbox\tidx*{ifvoid}�
b) \box0 % affiche la boite vide, le registre est maintenant "void"
  \ifzerodimbox0{vrai}{faux} (et \ifvoid0 void\else non void\fi)\par
c) \setbox0=\hbox{x}\ifzerodimbox0{vrai}{faux} (et \ifvoid0 void\else non void\fi)\par�\idx*\setbox�
d) \wd0=0pt \ht0=0pt \dp0=0pt % rend toutes les dimensions nulles
  \ifzerodimbox0{vrai}{faux} (et \ifvoid0 void\else non void\fi)\par�\idx*\setbox�
e) \setbox0=\vbox{}\ifzerodimbox0{vrai}{faux} (et \ifvoid0 void\else non void\fi)�\tidx*{ifvoid}�*\ifzerodimbox�/

Le test est n�gatif dans le cas c, seul cas o� le registre contient une boite de dimensions non nulles. Il est positif ailleurs, que la boite soit vide (cas a et e), que la boite soit non vide mais redimensionn�e (cas d) ou que le registre soit vide (cas b).
\grandsaut

Le moteur \idx\eTeX{}\idx*{moteur!etex} nous donne une autre m�thode, plus rapide et plus fiable pour tester si un registre de boite contient une boite \emph{vide}. Nous nous mettrons � l'abri du faux positif de l'exemple pr�c�dent (cas d) d'une boite non vide, mais redimensionn�e pour que toutes ses dimensions soient nulles.

La primitive \idx\lastnodetype de \idx\eTeX{} est de type registre d'entier et � tout moment, selon sa valeur qui varie de $-1$ � 15, caract�rise la nature du dernier n\oe ud compos�. Les diff�rents types sont expos�s dans le manuel d'\idx\eTeX. Le type qui nous int�resse ici est celui qui est qualifi� par l'entier $-1$ et qui caract�rise un n\oe ud vide, c'est-�-dire r�sultant d'une liste vide.

L'id�e est donc de composer le contenu de la boite, et de tester hors de cette boite si \idx\lastnodetype est strictement n�gatif, seul cas o� la boite sera vide. Nous allons mettre en \oe uvre cette m�thode pour construire une macro \emph{non d�veloppable} �\ifvoidorempty de syntaxe

\centrecode|\ifvoidorempty<registre>{<code vrai>}{<code faux>}|

\noindent qui renverra \verb|<code vrai>| si le \verb|<registre>| est vide ou contient une boite vide :

\showcode/\def\ifvoidorempty#1{% teste si le registre #1 est vide ou contient une boite vide��*\ifvoidorempty�
       \ifvoid#1\relax�\tidx*{ifvoid}�
               \expandafter\firstoftwo
       \else
               \begingroup% dans un groupe
                       \setbox0=% affecter � la boite 0�\idx*\setbox�
                               \ifhbox#1\hbox\bgroup\unhcopy% un boite horizontale�\idx*\hbox\tidx*{ifhbox}\idx*\unhcopy�
                               \else    \vbox\bgroup\unvcopy% ou verticale�\idx*\vbox\idx*\unvcopy�
                               \fi% dans laquelle on compose
                               #1\relax% #1 en dimensions naturelles
                               \expandafter\egroup% sauter la fin de la boite
                               \expandafter% et le \endgroup
               \endgroup
               \ifnum\lastnodetype=-1 % et tester si le dernier noeud est vide�\idx*\lastnodetype�
                       \expandafter\expandafter\expandafter\firstoftwo
               \else
                       \expandafter\expandafter\expandafter\secondoftwo
               \fi
       \fi
}
a) \setbox0=\hbox{}\ifvoidorempty0{vrai}{faux} (et \ifvoid0 void\else non void\fi)\par�\idx*\setbox\tidx*{ifvoid}�
b) \box0 % affiche la boite vide, le registre est maintenant "void"
  \ifvoidorempty0{vrai}{faux} (et \ifvoid0 void\else non void\fi)\par
c) \setbox0=\hbox{x}\ifvoidorempty0{vrai}{faux} (et \ifvoid0 void\else non void\fi)\par�\idx*\setbox�
d) \wd0=0pt \ht0=0pt \dp0=0pt % rend toutes les dimensions nulles
  \ifvoidorempty0{vrai}{faux} (et \ifvoid0 void\else non void\fi)\par�\idx*\setbox�
e) \setbox0=\vbox{}\ifvoidorempty0{vrai}{faux} (et \ifvoid0 void\else non void\fi)�\tidx*{ifvoid}\idx*\setbox�*\ifvoidorempty�/\idx*[|)]{boite!registre!vide}

\subsection{Mise en application}
Comment pourrions-nous enfermer dans une boite \idx\vtop des �l�ments mis dans des \idx\hbox qui soient tous centr�s horizontalement les uns par rapport aux autres ? Le but est d'�crire

\centrecode/\cvtop{Ligne du haut,Tr�s grande ligne du milieu,Ligne du bas pour finir}/

\noindent pour obtenir ceci

\begin{centrage}
\small
texte avant...\vtop{\halign{\hfil#\hfil\cr
Ligne du haut\cr Tr�s grande ligne de milieu\cr Ligne de bas pour finir\crcr}}...texte apr�s
\end{centrage}

Si nous empilons des \idx\hbox dans une \idx\vtop, nous ne pouvons pas centrer les \idx\hbox, car nous ne pouvons �crire ni \idx\hfill ni \idx\hss dans une \idx\vtop puisque le mat�riel y est vertical et que ces primitive, exclusivement horizontales, y sont interdites. Agir sur les ressorts de paragraphe \idx\leftskip et \idx\rightskip est sans effet puisque dans cette boite, \TeX{} ne compose pas de paragraphe, il ne fait qu'empiler des \idx\hbox verticalement.

La solution va consister � trouver la longueur $l$ de la plus longue \idx\hbox, puis composer toutes les boites \idx\hbox avec une longueur impos�e $l$ en ayant pris soin de centrer le contenu avec des ressorts \idx\hss plac�s en d�but et en fin de boite. La macro \verb|\doforeach| vue pr�c�demment nous sera d'un grand secours. La variable, que nous appelons \verb|\htext|, contiendra tout � tour � tour chaque �l�ment de la liste, mais il faudra proc�der en deux passes successives :

\begin{itemize}
       \item la premi�re trouvera, en les examinant tour � tour, la \idx\hbox la plus longue et cette dimension maximale sera stock�e dans le registre de dimension \verb|\maxhsize|;
       \item lors de la deuxi�me passe, nous �crirons � chaque it�ration

       \centrecode-\hbox to\maxhsize{\hss\htext\hss}-

       pour enfermer l'�l�ment courant dans une \idx\hbox de longueur \verb|\maxhsize| et centr� dans celle-ci � l'aide des ressorts-primitives \idx\hss.
\end{itemize}

Pour tester si la longueur de l'�l�ment consid�r� est plus grande que celle du pr�c�dent, il faut d'abord initialiser \verb|\hmaxsize| � la plus petite dimension permise qui est l'oppos� de la plus grande dimension \idx\maxdimen, registre de dimension d�fini dans plain-\TeX{} et qui vaut \verb|16383.99999pt|. Ensuite, si la dimension de l'�l�ment est strictement sup�rieure � \verb|\hmaxsize|, nous actualiserons \verb|\hmaxsize| � la longueur de l'�l�ment examin�. En fin de boucle, nous serons assur�s que \verb|\hmaxsize| est la plus grande longueur.�*\cvtop[|(]

\showcode|\newdimen\hmaxsize�\idx*\newdimen�
\def\cvtop#1{%��*\cvtop�
       \hmaxsize=-\maxdimen% initialise � la plus petite longueur�\idx*\maxdimen�
       \doforeach\htext\in{#1}% pour chaque �l�ment :��*\doforeach�
               {\setbox0=\hbox{\htext}% stocker l'�l�ment "\htext" dans une \hbox�\idx*\hbox\idx*\setbox�
               \ifdim\wd0 >\hmaxsize% si sa longueur est sup�rieure � \hmaxsize�\tidx*{ifdim}�
                       \hmaxsize=\wd0 % mettre � jour \hmaxsize�\idx*\wd�
               \fi
               }%
       \vtop{% dans une \vtop...�\idx*\vtop�
               \doforeach\htext\in{#1}% pour chaque �l�ment :��*\doforeach�
                       {\hbox to\hmaxsize{\hss\htext\hss}% le centrer dans une \hbox de longueur \hmaxsize�\idx*\hss�
                       }%
       }%
}

texte avant...\cvtop{Ligne du haut,Tr�s grande ligne du milieu,Ligne du bas pour finir}%
..texte apr�s|

\begin{exercice}
Proposer une autre fa�on de faire sans enfermer \verb|\htext| dans une \idx\hbox.
\solution
Chaque �l�ment peut �tre compos� comme un paragraphe. Pour cela, la longueur de la \idx\vtop doit �tre �gale � \verb|\hmaxsize|, l'indentation doit �tre nulle et pour que les paragraphes soient centr�s, \idx\leftskip et \idx\rightskip sont rendus �gaux � \texttt{0pt plus 1fil}.

Cela donne :

\showcode|\newdimen\hmaxsize�\idx*\newdimen�
\def\cvtop#1{%��*\cvtop�
       \hmaxsize=-\maxdimen% initialise � la plus petite longueur�\idx*\maxdimen�
       \doforeach\htext\in{#1}% pour chaque �l�ment :��*\doforeach�
               {\setbox0=\hbox{\htext}% stocker l'�l�ment "\htext" dans une \hbox�\idx*\hbox\idx*\setbox�
               \ifdim\wd0 >\hmaxsize% si sa longueur est sup�rieure � \hmaxsize�\tidx*{ifdim}�
                       \hmaxsize=\wd0 % mettre � jour \hmaxsize�\idx*\wd�
               \fi
               }%
       \vtop{% dans une \vtop...�\idx*\vtop�
               \hsize\hmaxsize % longueur de la \vtop = \maxhsize
               \parindent=0pt % pas d'indentation�\idx*\parindent�
               \leftskip=0pt plus1fil minus0pt \rightskip=\leftskip% ressorts de centrage�\idx*\leftskip\idx*\rightskip�
               \doforeach\htext\in{#1}% pour chaque �l�ment :��*\doforeach�
                       {\htext\par}% le composer et finir le paragraphe
       }%
}

texte avant...\cvtop{Ligne du haut,Tr�s grande ligne du milieu,Ligne du bas pour finir}%
..texte apr�s|�*\cvtop[|)]
\end{exercice}

Ces fa�ons de faire sont un peu tir�e par les cheveux. En effet, nous venons de programmer ce que fait (entre autres) la primitive de \TeX{} � \idx\halign\verb|{<code>}| �. Le but ici n'est pas d'en d�crire toutes ses fonctionnalit�s, car elles sont tr�s nombreuses et pour certaines, tr�s techniques\footnote{Pour en savoir plus, il est sage de se tourner vers le \TeX book, chapitre 22.}.

Pour aller � l'essentiel, cette primitive op�re en mode vertical\idx*{mode!vertical} et construit des alignements (autrement dit, des tableaux) constitu�s de lignes, elles-m�mes partag�es en cellules. Ce qui est remarquable, c'est que lorsque \idx\halign lit son argument, elle compose \emph{tous} les contenus des cellules et par cons�quent, fixe comme longueur d'une colonne la plus grande des longueurs rencontr�es dans cette colonne.

Du c�t� de la syntaxe, chaque ligne s'ach�ve par la primitive \idx\cr et il est prudent de placer \idx\crcr en fin de tableau. Au sein d'une ligne, le token  �\verb|&|� (de catcode \number\catcode`\&) signifie � passer � la colonne suivante�. La syntaxe d'une ligne est donc :

\centrecode-<cellule 1>&<cellule 2>& ... &<cellule n>\cr-

Raffinement suppl�mentaire, il est possible pour toutes les cellules d'une m�me colonne de d�finir un code qui sera ins�r� avant leur contenu et un code qui sera ins�r� apr�s. Pour cela, la primitive \idx\halign admet un \emph{pr�ambule} qui est plac� avant le premier \idx\cr. La syntaxe de ce pr�ambule reprend la syntaxe d'une ligne, mais le \verb|<contenu>| d'une cellule est symbolis� par le token �\cidx\#�. Ainsi, pour une colonne (c'est-�-dire compris entre deux �\cidx[ (caract�re d'alignement)]\&�), si on �crit dans le pr�ambule

\centrecode-<code avant>#<code apr�s>-

\noindent alors, le texte \verb|<code avant>| sera ins�r� avant le code contenu dans les cellules et \verb|<code apr�s>| sera ins�r� apr�s.

Dans l'exemple ci-dessous, la colonne \no1 est d�finie pour que �\verb|X|� soit affich� avant chaque cellule et �\verb|**\ignorespaces|� apr�s, o� \idx\ignorespaces nous assure qu'en dehors du pr�ambule, les espaces ins�r�s avant le premier \verb|&| ne compteront pas. Pour la deuxi�me colonne, \cidx\# est seul et donc les cellules de cette colonne seront compos�es sans aucun ajout. Enfin, la colonne \no3 est compos�e au fer � droite en ins�rant \idx\hfil � gauche de \cidx\# :

\showcode/\halign{X#**\ignorespaces&#&\hfil #\cr % pr�ambule�\idx*\halign\idx*\ignorespaces�
foo            &foo bar&123 456\cr % premi�re ligne�\idx*\cr�
deuxi�me ligne &1      &12\cr % deuxi�me ligne
a              &\TeX   &1 2 3 4 5 6\cr % troisi�me ligne
\crcr}�\idx*\crcr�/

Pour tirer parti de \idx\halign dans le code de �\cvtop[|(], nous allons d�finir un alignement � une colonne et nous sp�cifierons �\idx\hfil{}\cidx\#{}\idx\hfil� en pr�ambule afin que les contenus soient centr�s. � l'aide de �\substtocs, nous stockerons dans une macro \verb|\temp| l'argument de �\cvtop o� les virgules auront �t� remplac�es par \idx\cr. Il suffira ensuite de placer la macro \verb|\temp| juste apr�s le \idx\cr qui marque la fin du pr�ambule pour que \TeX{} la d�veloppe (car le d�but de chaque cellule est d�velopp�) pour constituer le corps du tableau :

\showcode|\def\cvtop#1{%��*\cvtop�
       \vtop{% \vtop assure que l'on est en mode vertical�\idx*\vtop\idx*{mode!vertical}�
               \substtocs\temp{#1}{,}{\cr}% dans \temp, remplacer les "," par "\cr"��\substtocs\idx*\cr�
               \halign{%�\idx*\halign�
                       \hfil##\hfil\cr% pr�ambule : centrer le contenu�\idx*\hfil�
                       \temp\crcr}% mettre \temp dans l'alignement�\idx*\crcr�
       }% \temp est d�truite en sortant de la boite
}

texte avant...\cvtop{Ligne du haut,Tr�s grande ligne du milieu,Ligne du bas pour finir}%
..texte apr�s|

Ce code en sugg�re un autre, capable de calculer � l'aide de \idx\halign, la plus grande longueur de textes. Pour cela, la macro �\calcmaxdim, de syntaxe

\centrecode-\calcmaxdim\<macro>{<texte 1>,texte 2>,...,<texte n>}-

\noindent stockera dans la \verb|\<macro>| la plus grande longueur des \verb|<texte>|.

\showcode/\def\calcmaxdim#1#2{%��*\calcmaxdim�
       \setbox0=\vtop{% \vtop assure que l'on est en mode vertical (interne)�\idx*\vtop\idx*\setbox�
               \substtocs\temp{#2}{,}{\cr}% dans \temp, remplacer les "," par "\cr"��*\substtocs\idx*\cr�
               \halign{##\hfil\cr% pr�ambule : composer au fer � gauche�\idx*\halign\idx*\hfil�
                       \temp\crcr}% mettre \temp dans l'alignement�\idx*\crcr�
       }% \temp est d�truite en sortant de la boite
       \edef#1{\the\wd0 }%�\idx*\the\idx*\wd�
}
a) La plus grande longueur vaut
  \calcmaxdim\foo{Ligne du haut,Tr�s grande ligne du milieu,Ligne du bas pour finir}\foo

b) V�rification : \setbox0=\hbox{Tr�s grande ligne du milieu}\the\wd0 �\idx*\setbox\idx*\the\idx*\wd�/�*\cvtop[|)]\idx*[|)]{boite}

\section{Les r�glures}\idx*[|(]{r�glure}
\subsection{Tracer des lignes}
Nous allons maintenant nous int�resser � des boites un peu particuli�res, les boites de r�glure ou �r�glures�, c'est-�-dire des boites enti�rement remplies de noir.

\begin{regle}
Les primitives \idx\hrule et \idx\vrule, qui op�rent respectivement en \idx*{mode!vertical}mode \emph{vertical} et \emph{horizontal}\idx*{mode!horizontal}, tracent des r�glures. Par d�faut, les dimensions de ces r�glures sont :

\begin{centrage}
       \small
       \begin{tabular}{rcc}\hline
               &\idx\hrule&\idx\vrule\\\hline
               largeur (width) & \verb|*| & 0.4pt\\
               hauteur (height)& 0.4pt&\verb|*|\\
               profondeur (depth)&0pt&\verb|*|\\\hline
       \end{tabular}
\end{centrage}

L'�toile signifie que la dimension est celle de la boite qui contient la r�glure.

Si l'on souhaite passer outre les valeurs par d�faut et imposer une ou plusieurs dimensions, on doit faire suivre ces deux primitives  d'un (ou plusieurs) mots-cl�s parmi �\verb|width|�, �\verb|height|� ou �\verb|depth|� et en respectant cet ordre. S'ils sont pr�sents, ces mots-cl�s doivent �tre suivis de la \verb|<dimension>| que l'on souhaite imposer.

Si plusieurs sp�cifications contradictoires sur une dimension sont sp�cifi�es, la derni�re est prise en compte.
\end{regle}

Voici par exemple ce que l'on obtient si on �crit �\idx\vrule� dans le code source imm�diatement apr�s ces deux points :\vrule. On constate que la r�glure, qui op�re en mode horizontal, a la largeur par d�faut de \verb|0.4pt| et a pour hauteur et profondeur celles de la boite dans laquelle elle est enferm�e. Cette boite est la ligne en cours de composition.

Passons maintenant � \idx\hrule et voici l'effet de �\idx\hrule� juste apr�s ces deux points :\hrule
La r�glure prend la totalit� de la largeur de la boite qui la contient. La boite dont il est question dans ce cas est la page elle-m�me, de largeur \idx\hsize, dans laquelle les �l�ments sont empil�s verticalement. On remarque que pour satisfaire son mode de fonctionnement, \idx\hrule passe en mode vertical\idx*{mode!vertical}. Puisque nous �tions � l'int�rieur d'un paragraphe, celui-ci a �t� compos� avant le passage en mode vertical. Par ailleurs, le \idx{ressort d'interligne} n'est pas ins�r�, ni avant la r�glure ni apr�s. Une r�glure \idx\hrule est donc dessin�e \emph{au plus pr�s} verticalement de ce qui la suit et de ce qui la pr�c�de.

L'exemple suivant montre que les primitives de r�glures utilis�es sans mot-cl� adaptent leurs dimensions � celles de la boite qui les contient. Ici, on dessine des \idx\hrule au sommet et au bas d'une \idx\vbox dans la premi�re ligne alors que l'on trace des \idx\vrule avant et apr�s une \idx\vtop � la deuxi�me ligne :

\showcode/a) .......\vbox{\hrule\hbox{foo}\hbox{ligne du bas}\hrule}.......\medbreak�\idx*\vbox\idx*\hrule\idx*\hbox�
b) .......\vrule\vtop{\hbox{foo}\hbox{ligne du bas}}\vrule.......�\idx*\vtop\idx*\vrule�/

On voit clairement au cas a que les \idx\hrule � l'int�rieur de \idx\vbox prennent chacune la largeur totale de la boite. En ce qui concerne les \idx\vrule qui se trouvent avant et apr�s la \idx\vtop au cas b, elles ont adapt� leur profondeur et hauteur pour s'�tendre sur la hauteur totale de la boite qui ici est la ligne en cours.

Voici maintenant des r�glures dont les dimensions sont impos�es par mots-cl�s :

\showcode/Une r�glure de 1.5cm :\hrule width1.5cm
foo\vrule width 2pt height .5cm depth .2cm bar/

Ici encore, la \idx\vrule est en contact avec la \idx\hrule puisque le \idx{ressort d'interligne} n'est pas ins�r�.

\begin{exercice}
�crire une macro �\showdim[|(], op�rant en mode horizontal\idx*{mode!horizontal}, dont l'argument est une dimension et qui repr�sente sous forme d'une r�glure horizontale la dimension donn�e.

Par exemple, ��\showdim\verb-{1.5cm}-� produit �\showdim{1.5cm}� o� les traits verticaux de d�but et de fin ont une hauteur de \verb|1ex|. Toutes les r�glures ont une �paisseur de \verb|0.4pt|.

\solution
Voici le code de cette macro :

\showcode/\def\showdim#1{%��*\showdim�
       \vrule width 0.4pt height 1ex  depth 0pt % trait vertical gauche�\idx*\vrule\defline\aaa�
       \vrule width #1    height0.4pt depth 0pt % r�glure horizontale de longueur #1�\defline\bbb�
       \vrule width 0.4pt height 1ex  depth 0pt % trait vertical droit�\idx*\vrule\defline\ccc�
       \relax% stoppe la lecture de la pr�c�dente dimension
}

a) une longueur de 1 cm : \showdim{1cm}\par
b) une longueur de 137,4 pt : \showdim{137,4pt}\par
c) une longueur de 2 mm : \showdim{2mm}/

Le code est tr�s simple. En premier lieu (ligne \no\aaa), la primitive \idx\vrule qui op�re en mode horizontal\idx*{mode!horizontal} trace une barre verticale d'\verb|1ex| de hauteur et de \verb|0.4pt| d'�paisseur. Ensuite, � la ligne \no\bbb, nous la faisons suivre d'une ligne horizontale dont la longueur a �t� forc�e � la dimension contenue dans l'argument et dont la hauteur est \verb|0.4pt|. Nous finissons � la ligne \no\ccc{} avec la m�me barre verticale qu'au d�but.�*\showdim[|)]
\end{exercice}

\subsection{Encadrer}\idx*[|(]{encadrer}
On commence � deviner qu'il serait assez facile de programmer une macro �\FRbox qui encadre tout ce qui est dans son argument, argument devant �tre compos� en mode horizontal\idx*{mode!horizontal} :

\centrecode|\FRbox{<contenu>}|�*\FRbox

Les deux param�tres importants pour l'aspect visuel sont l'�paisseur des r�glures et l'espacement entre elles et le contenu. Chacun de ces param�tres sera un registre de dimension; �\frboxrule pour l'�paisseur et �\frboxsep pour l'espacement\footnote{Ne pas confondre les noms de ces registres avec \texttt{\string\fboxrule} et \texttt{\string\fboxsep} qui sont les registres d�finis par \LaTeX{} pour les boites encadr�es avec la macro \texttt{\string\fbox}.}.

En ce qui concerne la m�thode pour encadrer un contenu arbitraire, il y a deux fa�ons diff�rentes de tracer les r�glures :

\begin{centrage}
       \leavevmode
       \frboxrule=0.2pt \frboxsep=1pt
       \small
       \vbox{%
               \offinterlineskip
               \hbox{\FRbox{\vrule height 1mm width\dimexpr2.2cm+2\frboxsep+2\frboxrule}}%
               \hbox{%
                       \FRbox{\vrule width1mm height\dimexpr1cm-2\frboxsep-2\frboxrule }%
                       \vbox to1cm{\vss\hbox to2cm{\hss\verb|<contenu>|\hss}\vss}%
                       \FRbox{\vrule width1mm height\dimexpr1cm-2\frboxsep-2\frboxrule }%
                       }%
               \hbox{\FRbox{\vrule height 1mm width\dimexpr2.2cm+2\frboxsep+2\frboxrule}}%
       }\hskip0pt plus1fil
       \hbox{%
               \FRbox{\vrule width1mm height\dimexpr1.2cm+2\frboxsep+2\frboxrule }%
               \vbox to\dimexpr1.2cm+4\frboxsep+4\frboxrule{%
                       \hbox{\FRbox{\vrule height1mm width\dimexpr2cm-2\frboxsep-2\frboxrule }}%
                       \vskip 0pt plus 1fil
                       \hbox to2cm{\hss \verb|<contenu>|\hss}%
                       \vskip 0pt plus 1fil
                       \hbox{\FRbox{\vrule height1mm width\dimexpr2cm-2\frboxsep-2\frboxrule }}%
               }%
               \FRbox{\vrule width1mm height\dimexpr1.2cm+2\frboxsep+2\frboxrule }%
       }%
\end{centrage}

\noindent D�cidons-nous par exemple pour la structure de droite. Pour arriver � nos fins, nous allons construire une \idx\vbox dans laquelle nous allons ins�rer, de haut en bas :

\begin{itemize}
       \item une r�glure horizontale ;
       \item une espace verticale �gale � �\frboxsep ;
       \item le contenu (pr�c�d� et suivi d'espaces �gales � �\frboxsep);
       \item une espace verticale �gale � �\frboxsep ;
       \item une r�glure horizontale.
\end{itemize}

\noindent Nous obtiendrons donc :

\begin{centrage}
       \leavevmode
       \small
       \frboxrule=0.2pt \frboxsep=1pt
       \hbox{%
               \vbox to\dimexpr1.2cm+4\frboxsep+4\frboxrule{%
                       \hbox{\FRbox{\vrule height1mm width\dimexpr2cm-2\frboxsep-2\frboxrule }}%
                       \vskip 0pt plus 1fil
                       \hbox to2cm{\hss\verb|<contenu>|\hss}%
                       \vskip 0pt plus 1fil
                       \hbox{\FRbox{\vrule height1mm width\dimexpr2cm-2\frboxsep-2\frboxrule }}%
               }%
       }%
\end{centrage}

\Qu 'ils soient horizontaux ou verticaux, tous les espaces seront ins�r�s avec la primitive \idx\kern qui agit selon le mode en cours. Voici la construction obtenue pour un contenu �gal au mot � Programmation � :

\showcode/�\verb-\newdimen\frboxrule \newdimen\frboxsep-\idx*\newdimen�*\frboxrule�*\frboxsep�
\frboxsep=5pt \frboxrule=1pt ��*\frboxsep �*\frboxrule�
\leavevmode�\idx*\leavevmode�
..%
\vbox{%�\idx*\vbox�
       \hrule height\frboxrule% r�glure sup�rieure�\idx*\hrule�
       \kern\frboxsep% espace verticale haute�\idx*\kern�
       \hbox{\kern\frboxsep Programmation\kern\frboxsep}% contenu + espaces horizontales�\idx*\hbox�
       \kern\frboxsep% espace verticale basse��*\frboxsep�
       \hrule height\frboxrule% r�glure inf�rieure��*\frboxrule�
       }%
../

\noindent Il ne reste plus qu'� envelopper le tout dans une boite horizontale \idx\hbox, apr�s avoir fait pr�c�der la \idx\vbox de \idx\vrule qui seront les r�glures verticales � droite et � gauche de l'encadrement�*\FRbox :

\showcode|�\verb-\newdimen\frboxrule \newdimen\frboxsep-\idx*\newdimen�*\frboxrule�*\frboxsep�
\frboxsep=5pt \frboxrule=0.6pt
\def\FRbox#1{% /!\ ne change pas le mode H ou V en cours��*\FRbox�
       \hbox{% mettre � la suite horizontalement les 3 choses suivantes :�\idx*\hbox�
               \vrule width\frboxrule% 1) r�glure gauche�\idx*\vrule�
               \vbox{%                 2) un empilement vertical comprenant�\idx*\vbox�
                       \hrule height\frboxrule% a) r�glure sup�rieure�\idx*\hrule �
                       \kern\frboxsep%          b) espace verticale haute�\idx*\kern �
                       \hbox{%                  c) contenu + espaces en mode H
                               \kern\frboxsep#1\kern\frboxsep�\defline\ccc�
                       }%
                       \kern\frboxsep%          d) espace verticale basse�\defline\aaa�*\frboxsep�
                       \hrule height\frboxrule% e)r�glure inf�rieure�\defline\bbb�
                       }%
               \vrule width\frboxrule% 3) r�glure droite�\idx*\vrule�*\frboxrule�
       }%
}
Ligne de base : ...\FRbox{Programmation}...%
\frboxrule=2pt \FRbox{Programmation}...%
\frboxsep=0pt \FRbox{Programmation}...%
\frboxrule0.4pt \FRbox{Programmation}...��*\FRbox�|

On constate que la \idx{ligne de base} du contenu des boites n'est pas align�e avec la \idx{ligne de base} de la ligne en cours. En fait, comme la \idx\vbox empile les �l�ments au-dessus de la \idx{ligne de base} du dernier �l�ment, le \idx{point de r�f�rence} de la \idx\vbox se trouve sur la \idx{ligne de base} de la r�glure inf�rieure trac�e � la ligne \no\bbb, c'est-�-dire au niveau du bord \emph{inf�rieur} de cette r�glure\footnote{Si nous avions �crit \texttt{depth} au lieu de \texttt{height} � la ligne \no\bbb, le point de r�f�rence aurait �t� au niveau du bord \emph{sup�rieur} de la r�glure du bas.}. Le probl�me qui se pose est le suivant : comment construire une boite verticale o� l'on place des listes de mat�riels verticaux

\centrecode-<liste a>
<liste b>-

\noindent et faire en sorte que le \idx{point de r�f�rence} de la boite ainsi construite soit sur la \idx{ligne de base} du dernier �l�ment vertical de \verb|<liste a>| ? Faire appel � \idx\vbox ou \idx\vtop seules ne peut convenir. Il fait \emph{combiner} ces deux boites. L'id�e est d'enfermer \verb|<liste a>| dans une \idx\vbox et mettre cette \idx\vbox comme premier �l�ment vertical d'une \idx\vtop qui englobe le tout. La boite ainsi construite a la structure suivante\label{frbox.ligne.de.base} :

\centrecode-\vtop{%�\idx*\vtop�
       \vbox{<liste a>}
       <liste b>
}-

De par les d�finitions de \idx\vbox et \idx\vtop, le \idx{point de r�f�rence} de la boite externe \idx\vtop se trouvera sur la \idx{ligne de base} du dernier �l�ment vertical de \verb|<liste a>|. Voici un exemple qui illustre cette manipulation :

\showcode/Persuadez-vous que :
\vtop{�\idx*\vtop�
       \vbox{�\idx*\vbox�
               \hbox{Programmer}�\idx*\hbox�
               \hbox{en}
               \hbox{\TeX}
               \hbox{est}% <- ligne de base de la \vtop
       }
       \hbox{\it tout sauf}�\idx*\it�
       \hbox{facile.}
}/

Nous allons appliquer cette structure pour cr�er une nouvelle macro �\frbox[|(] afin que, contrairement � �\FRbox, le point de r�f�rence du cadre soit au niveau de la \idx{ligne de base} du contenu. Il faut donc rejeter hors de la \idx\vbox les mat�riels verticaux des lignes \nos\aaa{} et \bbb{} :

\showcode/%\newdimen\frboxrule \newdimen\frboxsep
\frboxrule=0.4pt \frboxsep=2pt
\def\frbox#1{% ne pas changer le mode H ou V en cours��*\frbox�
       \hbox{% enferme dans une \hbox�\idx*\hbox�
               \vrule width\frboxrule% r�glure gauche�\idx*\vrule�*\frboxrule�
               \vtop{%�\idx*\vtop�
                       \vbox{% 1er �l�ment de la \vtop�\idx*\vbox�
                               \hrule height\frboxrule% r�glure sup�rieure�\idx*\hrule�
                               \kern\frboxsep% espace haut�\idx*\kern�
                               \hbox{%�\idx*\hbox�
                                       \kern\frboxsep% espace gauche
                                       #1% contenu
                                       \kern\frboxsep% espace droite� �*\frboxsep�
                                       }%
                       }% puis autres �l�ments de la \vtop, sous la ligne de base
                       \kern\frboxsep% espace bas
                       \hrule height\frboxrule% r�glure inf�rieure
               }%
               \vrule width\frboxrule% r�glure droite�\idx*\vrule �*\frboxrule�
       }%
}
Ligne de base : ......\frbox{Programmation}......%
\frboxrule=2pt \frbox{Programmation}......%
\frboxsep=0pt \frbox{Programmation}......%
\frboxrule0.4pt \frbox{Programmation}......��*\frbox�/

\begin{exercice}
Cr�er une macro �\centretitre\verb|{<texte>}| dont l'argument doit �tre compos� dans un cadre (via �\frbox) qui prend toute la largeur de composition, c'est-�-dire \idx\hsize. L'argument doit �tre centr� dans ce cadre.
\solution
Tout d'abord, nous allons placer en d�but de macro un \verb|\medbreak| ce qui aura pour effet de composer le paragraphe en cours si la macro est appel�e en mode horizontal\idx*{mode!horizontal} et sautera une espace verticale. Ensuite, la primitive \idx\noindent interdira le placement de la boite d'indentation en d�but de paragraphe, et provoquera le passage en mode horizontal\idx*{mode!horizontal}.

Nous allons composer le \verb|<texte>| dans une boite verticale \idx\vbox. Sa dimension horizontale, sp�cifi�e par \idx\hsize, doit tenir compte des r�glures droite et gauche (chacune de dimension �\frboxrule) ainsi que les espaces � droite et � gauche entre le \verb|<texte>| et les r�glures (chacun de dimension �\frboxsep). La dimension horizontale de la boite sera donc

\begin{centrage}
       \small$\hbox{\verb|\hsize|}-2\hbox{�\frboxrule}-2\hbox{�\frboxrule}$\idx*\hsize
\end{centrage}

Pour que le centrage soit effectif, nous jouerons sur les ressorts \idx\leftskip et \idx\rightskip sans oublier d'annuler le ressort de fin de paragraphe\idx*{paragraphe!centrage} \idx\parfillskip.

\showcode/\def\centretitre#1{%��*\centretitre�
       \medbreak% passe en mode v puis saute une espace verticale�\idx*\medbreak�
       \noindent% pas d'indentation et passe en mode horizontal�\idx*\noindent\idx*{mode!horizontal}�
       \frbox{% encadre��*\frbox�
               \vbox{% une boite verticale�\idx*\vbox�
                       \hsize=\dimexpr\hsize-2\frboxrule-2\frboxsep\relax�\idx*\hsize\idx*\dimexpr �*\frboxsep �*\frboxrule�
                       \parindent=0pt % pas d'indentation�\idx*\parindent�
                       \leftskip=0pt plus1fil \rightskip=\leftskip% ressorts de centrage�\idx*\leftskip\idx*\rightskip�
                       \parfillskip=0pt % annule le ressort de fin de paragraphe�\idx*\parfillskip�
                       #1% ins�re le titre
                       \endgraf% et le compose�\idx*\endgraf�
                       }%
       }%
       \medbreak% passe en mode v puis saute une espace verticale�\idx*\medbreak�
       \ignorespaces% mange les espaces situ�s apr�s la macro \centretitre�\idx*\ignorespaces�
}
\frboxrule=0.8pt \frboxsep=5pt
Voici un
\centretitre{Titre}
puis un
\centretitre{Texte tr�s long pour composer un titre qui va prendre plusieurs
lignes et pour s'assurer que la composition s'effectue correctement}��*\centretitre�/
\end{exercice}�*\frbox[|)]\idx*[|)]{encadrer}

\idx*[|(]{souligner}\begin{exercice}
Programmer une macro �\souligne\verb|{<texte>}| qui souligne d'un trait de 0.4pt d'�paisseur le \verb|<texte>|. Le trait de soulignement devra se situer � \verb|1pt| au-dessous du \verb|<texte>| :

\begin{centrage}
\small
\begin{tabular}{>{\ttfamily\hfill}r<{\kern1.5em \normalfont affiche\kern1.5em}@{}l}
\string\souligne\{Du texte\}&\souligne{Du texte}\\
\string\souligne\{Du texte profond\}&\souligne{Du texte profond}
\end{tabular}
\end{centrage}

Proposer une variante �\Souligne o� le trait devra se situer � 1pt au-dessous de la \idx{ligne de base}, quelle que soit la profondeur du texte � souligner :

\begin{centrage}
\small
\begin{tabular}{>{\ttfamily\hfill}r<{\kern1.5em \normalfont affiche\kern1.5em}@{}l}
\string\Souligne\{Du texte\}&\Souligne{Du texte}\\
\string\Souligne\{Du texte profond\}&\Souligne{Du texte profond}
\end{tabular}
\end{centrage}

\solution
Nous devons tracer une r�glure ayant comme dimension horizontale celle de la \idx\hbox dans laquelle est plac� l'argument. Afin de pouvoir mesurer cette boite, nous allons stocker \verb|\hbox{#1}| dans le registre de boite \no0\idx*{boite!\no0}.

Mais avant de poursuivre, regardons d'un peu plus pr�s les dimensions qui suivent les mots-cl�s \verb|height|, \verb|width| et \verb|depth|, et consid�rons-les comme des dimensions \emph{sign�es}. Car c'est ainsi que \TeX{} travaille; rien ne dit qu'une dimension, f�t-elle de r�glure, doit �tre positive ! Par exemple, pour tracer une r�glure de \verb|0.4pt| d'�paisseur � \verb|10pt| de hauteur, nous pouvons fixer sa hauteur � \verb|10.4pt| et sa profondeur � \verb|-10pt| :

\showcode/Une r�glure en hauteur : \vrule width 1cm height 10.4pt depth -10pt �\idx*\vrule�/

De m�me, pour tracer une r�glure d'�paisseur \verb|0.4pt| � \verb|2pt| sous la \idx{ligne de base}, il suffit de fixer sa profondeur � \verb|2.4pt| et sa hauteur � \verb|-2pt| :

\showcode/Une r�glure en dessous: \vrule width 1cm depth 2.4pt height -2pt �\idx*\vrule�/

Revenons � notre probl�me\ldots{} Nous stockerons la \idx\hbox dans le registre de boite \no0\idx*{boite!\no0}. Puis, nous allons appliquer l'astuce expos�e ci-dessus pour tracer une r�glure de \verb|0.4pt| d'�paisseur � une distance de \verb|\dp0+1pt| sous la \idx{ligne de base}. Pour cela, nous allons stocker dans ce m�me registre \no0\idx*{boite!\no0} une \idx\vrule dont la longueur est celle du texte � souligner, soit \verb|\wd0|, de profondeur \verb|\dp0+1.4pt| et de hauteur n�gative �gale � \verb|-\dp0-1pt|. Nous allons ensuite rendre nulles toutes les dimensions de la boite afin que son encombrement soit nul dans toutes les directions. Enfin, apr�s �tre �ventuellement sorti du mode vertical\idx*{mode!vertical}, nous affichons cette boite \no0\idx*{boite!\no0} avant le texte  :

\showcode/\def\souligne#1{%��*\souligne�
       \setbox0=\hbox{#1}% stocke le contenu dans le registre no 0�\idx*\setbox�
       \setbox0=\hbox{% puis, dans une \hbox, construit une r�glure�\idx*\setbox�
               \vrule width\wd0 % de la longueur du contenu�\idx*\vrule\idx*\wd�
                       depth\dimexpr\dp0 + 1.4pt\relax % dp = profondeur texte + 1.4pt�\idx*\dimexpr�
                       height\dimexpr-\dp0 - 1pt\relax % ht = -profondeux texte - 1pt
       }%
       \wd0=0pt \dp0=0pt \ht0=0pt % annule toutes les dimensions�\idx*\wd\idx*\ht\idx*\dp�
       \leavevmode \box0 % affiche la r�glure�\idx*\leavevmode\idx*\box�
       #1% puis le contenu
}
Voici \souligne{du texte normal}.\par
Voici \souligne{du texte profond}.��*\souligne�/

Compte tenu des dimensions utilis�es, le bord sup�rieur de la r�glure est tr�s exactement � \verb|1pt| sous la plus basse partie du texte � souligner.

La variante �\Souligne est plus simple : il ne faut pas tenir compte de la profondeur du registre \no0\idx*{boite!\no0}.

\showcode/\def\Souligne#1{%��*\Souligne�
       \setbox0=\hbox{#1}%�\idx*\setbox�
       \setbox0=\hbox{\vrule width\wd0 depth1.4pt height-1pt }%�\idx*\vrule\idx*\wd�
       \wd0=0pt \dp0=0pt \ht0=0pt �\idx*\wd\idx*\ht\idx*\dp�
       \leavevmode \box0 #1%�\idx*\leavevmode\idx*\box�
}
Voici \Souligne{du texte normal}.\par
Voici \Souligne{du texte profond}.��*\Souligne�/

Les macros pr�sent�es ici ne permettent pas de souligner un texte trop long ou trop proche d'une \idx{fin de ligne}, car une r�glure, \emph{a fortiori} enferm�e dans une \idx\hbox, ne peut franchir une coupure de ligne.

Une autre m�thode, impliquant \idx\lower, aurait �galement �t� envisageable :

\showcode/\def\Souligne#1{%
       \setbox0=\hbox{#1}%�\idx*\setbox�
       \lower 1pt % abaisser � 1pt sous la ligne de base�\idx*\lower�
               \rlap{% une \hbox en surimpression vers la droite�\idx*\rlap�
                       \vrule width\wd0 height0pt depth0.4pt % contenant le soulignement
               }%
       #1% puis afficher le <texte>
}
Voici \Souligne{du texte normal}.\par
Voici \Souligne{du texte profond}.��*\Souligne�/

La m�thode n'est pas �quivalente car dans ce dernier cas, la r�glure qui tient lieu de soulignement est prise en compte dans la boite englobante de �\Souligne\verb|<texte>|, ce qui n'�tait pas le cas dans le premier code.
\end{exercice}\idx*[|)]{souligner}

\subsection{Empiler des boites}\idx*[|(]{boite!empilement}
Essayons maintenant de jouer avec les boites et pour cela, cr�ons une macro �\stackbox capable d'empiler des boites encadr�es, toutes identiques, aussi bien horizontalement que verticalement. Le fait qu'elles soient identiques implique �videmment que les dimensions de leurs contenus ne sont pas trop diff�rentes. La syntaxe de la macro �\stackbox pourrait �tre :

\centrecode-\stackbox{a,bc,,d\\e,foobar,g\\123,456,$\alpha$,$x+y$,}-

\noindent Et le r�sultat serait :

\begin{centrage}
\small\vbox{\frboxsep=3pt \stackbox{a,bc,,d\\e,foobar,g\\123,456,$\alpha$,$x+y$,}}
\end{centrage}

En ce qui concerne les dimensions des boites, on pourrait parcourir lors d'une premi�re passe tous les arguments afin de trouver la plus grande des hauteurs, largueurs et profondeurs et ensuite prendre ces maximums comme dimension de chaque boite, qui seraient alors compos�es lors d'une seconde passe. Afin de ne pas inutilement compliquer le code\footnote{La vraie et inavouable raison est que renoncer � faire deux passes va nous donner l'occasion de d�couvrir les � \idx{strut}s � !}, nous allons plut�t d�cider que l'utilisateur va lui-m�me fixer la largueur \emph{interne} des cadres � l'aide d'un registre de dimension \verb|\stackwd| cr�� pour l'occasion : ceci suppose �videmment qu'aucune boite ne doit avoir un contenu dont la largeur exc�de \verb|\stackwd|.

Parcourir l'ensemble des contenus va �tre facilit�e avec la macro �\doforeach � qui nous donnerons la liste d'�l�ments d'une m�me ligne. Tout cela se fait ais�ment avec une macro \verb|\stackbox@i| � arguments d�limit�s par �\verb|\\|� dont le but est d'isoler et lire  la ligne en cours. Son texte de param�tre sera :

\centrecode-\def\stackbox@i#1\\{...}-

En premier lieu, la macro chapeau se contentera d'appeler la macro r�cursive \verb|\stackbox@i| de cette fa�on :

\centrecode-\stackbox@i#1\\\quark\\-�*\quark

\noindent Ceci a deux avantages : c'est l'assurance que \verb|\\| est pr�sent dans l'argument, car apr�s tout, on pourrait ne pas l'�crire dans l'argument de �\stackbox si on ne voulait qu'une seule ligne. L'autre avantage est que la derni�re ligne � lire est le \idx{quark} ��\quark�. Si la \tidx[|etc]{ifx}-�galit� de l'argument \verb|#1| avec �\quark est vraie, nous serons alors surs que la ligne pr�c�dente �tait la derni�re et donc, finir le processus. Nous aurons donc lu la totalit� des lignes une premi�re fois dans la macro chapeau puis chaque ligne une seule fois dans la macro r�cursive. Chaque ligne a �t� donc lue deux fois exactement. C'est la m�thode pr�conis�e par la r�gle de la page~\pageref{lire.arguments} pour lire une s�rie d'arguments.

La macro \idx\nobreak, ins�r�e avant chaque ligne restante, interdit toute coupure de page entre deux lignes de boites cons�cutives. Cette macro est d�finie dans plain-\TeX{} et son texte de remplacement est � \idx\penalty\verb|10000| �. Sachant que toute p�nalit� sup�rieure � \numprint{10000} est comprise comme \numprint{10000}, il s'agit l� de la plus forte \idx{p�nalit�} possible ce qui explique qu'une coupure de page ne se fera jamais � cet endroit.

\showcode/\newdimen\stackwd \stackwd=3em % dimension horizontale interne des cadres�\idx*\newdimen�
\catcode`@11
\def\stackbox#1{%��*\stackbox�
       \par% termine le paragraphe en cours
       \noindent�\idx\noindent�
       \stackbox@i#1\\\quark\\% ajoute "\\\quark\\" � la fin et appelle \stackbox@i��*\quark�
       \par
}

\def\stackbox@i#1\\{% #1=ligne courante
       \def\temp@{#1}% stocke la ligne courante
       \unless\ifx\quark\temp@% si ce n'est pas la fin�\tidx*{unless}�*\quark�
               \hfill % ressort infini de centrage (et fait passer en mode horizontal)�\idx*\hfill\idx*{mode!horizontal}�
               \noindent�\idx*\noindent�
               \doforeach\current@item\in{#1}% pour chaque �l�ment dans la ligne courante...��*\doforeach�
                       {\frbox{% ...encadrer��*\frbox�
                               \hbox to\stackwd{% une \hbox de largeur \stackwd�\idx*\hbox�
                                       \hss% ressort de centrage�\idx*\hss�
                                       \current@item% l'�l�ment courant
                                       \hss% ressort de centrage
                                       }
                               }% fin de la \frbox
                       }% fin \doforeach
               \hfill% ressort infini de centrage�\idx*\hfill�
               \null% assure que le dernier ressort est pris en compte�\idx*\null�
               \par% finir le paragraphe
               \nobreak% interdire une coupure de page�\idx*\nobreak�
               \nointerlineskip% ne pas ins�rer le ressort d'interligne�\idx*\nointerlineskip�
               \expandafter\stackbox@i% et recommencer
       \fi
}
\catcode`@12

\frboxrule=0.5pt \frboxsep=3pt ��*\frboxsep �*\frboxrule�
\stackbox{a,bc,,d\\e,foobar,g\\123,456,$\alpha$,$x+y$,}��*\stackbox�/

Le r�sultat est loin d'�tre celui escompt� ! \Qu oique pas si loin que �a, apr�s tout : les positions horizontales sont bonnes. Le bug vient du fait que nous n'avions pas pr�vu que les dimensions verticales (hauteur et profondeur) des �l�ments influaient naturellement sur la boite encadr�e construite. On peut y rem�dier en ins�rant un � \idx{strut}\footnote{On dit � poutre � en fran�ais mais ce mot est assez peu usit�.} � : c'est une r�glure invisible, mais qui s'�tend sur une dimension horizontale ou verticale. La question que l'on se pose imm�diatement est � comment rendre une r�glure invisible ?� Tout simplement en mettant sa largeur � \verb|0pt|, auquel cas elle aura une dimension verticale ou bien en mettant sa hauteur et profondeur � \verb|0pt| et dans ce cas, elle aura alors une dimension horizontale. Comme il est assez difficile de montrer des choses invisibles, voici une r�glure de type \idx\vrule rendue visible (son �paisseur est \verb|0.2pt|) apr�s la lettre � a � :

\showcode/a\vrule width0.2pt height15pt depth0pt \quad�\idx*\vrule�
a\vrule width0.2pt height0pt depth5pt \quad
a\vrule width0.2pt height10pt depth10pt \quad
a\vrule width1cm height0.2pt depth0pt�\idx*\vrule�/

Il suffit d'imposer \verb|0pt| comme dimension d'�paisseur pour rendre cette r�glure invisible, mais bien r�elle en ce qui concerne son encombrement. Voici comment la mettre en �vidence en encadrant au plus proche l'ensemble form� par la lettre �a� et le \idx{strut} :

\showcode/\frboxsep0pt %encadrement au plus proche��*\frboxsep�
\leavevmode�\idx*\leavevmode�
\frbox{a\vrule width0pt height15pt depth0pt }\quad��*\frbox\idx*\vrule�
\frbox{a\vrule width0pt height0pt depth5pt }\quad
\frbox{a\vrule width0pt height10pt depth10pt }\quad
\frbox{a\vrule width1cm height0pt depth0pt }�\idx*\vrule�*\frbox�/

\begin{exercice}
Construire une macro �\rectangle\verb|{<x>}{<y>}| o� \verb|<x>| et \verb|<y>| sont des dimensions et qui construit un rectangle dont les dimensions internes (c'est-�-dire de bord interne � bord interne) sont \verb|<x>| et \verb|<y>|.
\solution
Il faut construire une �\frbox dans laquelle nous allons mettre \emph{deux} \idx{strut}s, l'un pour la dimension verticale et l'autre pour l'horizontale.

\showcode/\def\rectangle#1#2{%��*\rectangle�
       \begingroup% dans un groupe
               \frboxsep = 0pt % encadrer au plus proche��*\frboxsep�
               \frboxrule= 0.4pt % en traits assez fins
               \frbox{%��*\frbox�
                       \vrule width#1 height0pt depth0pt %strut horizontal�\idx*\vrule�
                       \vrule width0pt height#2 depth0pt %strut vertical�\idx*\vrule�
               }%
       \endgroup% fermer le groupe
}
Carr� de 0.5 cm : \rectangle{0.5cm}{0.5cm}\smallskip�\idx*\smallskip�

Rectangle de 2.5cm par 3pt : \rectangle{2.5cm}{3pt}��*\rectangle�/
\end{exercice}

Pour nos boites cr��es avec �\stackbox, nous allons mettre dans chacune d'elles un \idx{strut} dont les dimensions verticales sont les plus grandes que l'on peut rencontrer dans un texte � normal �. Nous prendrons les dimensions verticales d'une \idx\hbox contenant ��gjp�. Bien �videmment, si un �l�ment contient un texte dont les dimensions verticales exc�dent celles du \idx{strut}, le probl�me r�apparaitra.

Il y a un autre d�faut, plus difficile � d�tecter dans notre macro �\stackbox : les r�glures des boites adjacentes ne se superposent pas, aussi bien horizontalement que verticalement, ce qui fait que leurs �paisseurs s'additionnent. Lorsque �\frboxrule est faible (\verb|0.5pt| ici), cela n'a pas d'influence visuelle notable, mais ce d�faut serait beaucoup plus visible si �\frboxrule valait 2pt par exemple. Nous allons donc ins�rer une espace n�gative avec \verb|\kern-\frboxrule| entre chaque boite horizontalement et entre chaque ligne verticalement. Le dernier \idx\kern horizontal, qui viendra apr�s la derni�re boite dans la boucle, sera annul� par la primitive \idx\unkern que nous mettons apr�s la boucle :

\showcode|\newdimen\stackwd \stackwd=3em �\idx*\newdimen�
\catcode`\@11
\def\stackbox#1{%��*\stackbox�
       \par% termine le paragraphe en cours
       \begingroup% dans un groupe semi-simple
               \parindent=0pt% pas d'indentation�\idx*\parindent�
               \parskip=0pt% annuler le \parskip�\idx*\parskip�
               \setbox0\hbox{�gjp}% boite pour le strut�\idx*\setbox\idx*\hbox�
               \edef\stack@strut{\vrule width\z@ height\the\ht0 depth\the\dp0 }% d�finit le strut�\idx*\vrule\idx*\z@�
               \stackbox@i#1\\\quark\\% ajoute "\\\quark\\" � la fin et appelle \stackbox@i��*\quark�
               \unkern% annule la derni�re compensation verticale
               \par
       \endgroup
}
\def\stackbox@i#1\\{% #1=ligne courante
       \def\temp@{#1}% stocke la ligne courante
       \unless\ifx\quark\temp@% si ce n'est pas la fin�\tidx*{unless}�*\quark�
               \hfill % ressort infini de centrage (passe en mode horizontal)�\idx*\hfill\idx*{mode!horizontal}�
               \doforeach\current@item\in{#1}% pour chaque �l�ment dans la ligne courante...��*\doforeach�
                       {\frbox{% ...encadrer��*\frbox�
                               \hbox to\stackwd{% une \hbox de largeur \stackwd contenant�\idx*\hbox�
                                       \hss%         1) ressort de centrage�\idx*\hss�
                                       \stack@strut% 2) strut de dimension verticale
                                       \current@item%3) l'�lement courant
                                       \hss}%        4)ressort de centrage
                               }% fin de la \fbox
                       \kern-\frboxrule% revenir en arri�re pour superposer les r�glures verticales�\idx*\kern�
                       }% fin de \doforeach
               \unkern% annuler la derni�re compensation horizontale�\idx*\unkern�
               \hfill% ressort infini de centrage�\idx*\hfill�
               \null% fait prendre en compte le dernier ressort�\idx*\null�
               \par% termine le paragraphe
               \nobreak% interdit une coupure de page�\idx*\nobreak�
               \nointerlineskip% sinon, ne pas ajouter le ressort d'interligne�\idx*\nointerlineskip�
               \kern-\frboxrule% superposer les r�glures horizontales�\idx*\kern�*\frboxrule�
               \expandafter\stackbox@i% et recommencer
       \fi
}
\frboxrule=0.5pt ��*\frboxrule�
\frboxsep=3pt ��*\frboxsep�
\stackbox{a,bc,,d\\e,foobar,g\\123,456,$\alpha$,$x+y$,}|

\begin{exercice}
Modifier la macro �\stackbox en �\lineboxed[|(] de telle sorte que pour chaque ligne, les boites aient une largeur telle qu'elles occupent la totalit� de la ligne.
\solution
Pour que la largeur des boites d'une ligne soit telle que toutes ces boites remplissent la ligne, nous devons d'abord savoir combien il y a de boites dans chaque ligne. Pour cela, il faut compter combien de virgules il y a dans l'argument \verb|#1| et ajouter 1 ou, m�thode plus simple, rajouter une virgule � \verb|#1| et effectuer le comptage. La macro �\cnttimestocs se chargera de ce travail et assignera le nombre de boites $n$ dans une macro.

La largeur disponible pour tous les contenus cumul�s de toutes les boites de la ligne s'obtient en retirant de \idx\hsize l'�paisseur �\frboxrule des r�glures verticales et les espaces �\frboxsep entre ces r�glures et les contenus des boites. S'il y a $n$ boites, il y a $n+1$ r�glures verticales et $2n$ espaces �\frboxsep. La largeur interne d'une boite, stock�e dans la macro \verb|\dim@box| sera donc

\[
\frac{\hbox{\ttfamily\char`\\hsize}-(n+1)\hbox{\ttfamily\char`\\frboxrule}-2n\hbox{\ttfamily\char`\\frboxsep}}{n}
\]

\showcode|\catcode`\@11
\def\lineboxed#1{%��*\lineboxed�
       \par% termine le paragraphe en cours
       \begingroup% dans un groupe semi-simple
               \parindent=0pt% pas d'indentation�\idx*\parindent�
               \parskip=0pt% annuler le \parskip�\idx*\parskip�
               \setbox0\hbox{�gjp}% boite pour le strut�\idx*\setbox\idx*\hbox�
               \edef\stack@strut{\vrule width\z@ height\the\ht0 depth\the\dp0 }% d�finit le strut�\idx*\vrule\idx*\z@�
               \lineboxed@i#1\\\quark\\% ajoute "\\\quark\\" � la fin et appelle la macro r�cursive��*\quark�
               \unkern% annule la derni�re compensation verticale
               \par
       \endgroup
}
\def\lineboxed@i#1\\{% #1=ligne courante
       \def\temp@{#1}% stocke la ligne courante
       \unless\ifx\quark\temp@% si ce n'est pas la fin�\tidx*{unless}�*\quark�
               \cnttimestocs{#1,}{,}\nb@args% re�oit le nombre d'arguments dans la ligne courante��*\cnttimestocs�
               \edef\dim@box{\the\dimexpr(\hsize-\frboxrule*(\nb@args+1)-
                             \frboxsep*2*\nb@args)/\nb@args}%�\idx*\the\idx*\dimexpr�*\frboxrule�*\frboxsep�
               \hbox{%�\idx*\hbox�
                       \doforeach\current@item\in{#1}% pour chaque �l�ment dans la ligne courante...��*\doforeach�
                               {\frbox{% ...encadrer��*\frbox�
                                       \hbox to\dim@box{% une \hbox de largeur \dim@box contenant
                                               \hss%         1) ressort de centrage�\idx*\hss�
                                               \stack@strut% 2) strut de dimension verticale
                                               \current@item%3) l'�lement courant
                                               \hss}%        4)ressort de centrage
                                       }% fin de la \fbox
                               \kern-\frboxrule% revenir en arri�re pour superposer les r�glures verticales�\idx*\kern�*\frboxrule�
                               }% fin de \doforeach
                       \unkern% annuler la derni�re compensation horizontale�\idx*\unkern�
               }%
               \par% termine le paragraphe
               \nobreak% interdit une coupure de page�\idx*\nobreak�
               \nointerlineskip% sinon, ne pas ajouter le ressort d'interligne�\idx*\nointerlineskip�
               \kern-\frboxrule% superposer les r�glures horizontales�\idx*\kern�*\frboxrule�
               \expandafter\lineboxed@i% et recommencer
       \fi
}
\catcode`\@12
\lineboxed{a,bc,,d\\e,foobar,g\\123,456,$\alpha$,$x+y$,}\medbreak�\idx*\medbreak�

\frboxrule=1.5pt ��*\frboxrule�
\frboxsep=3pt ��*\frboxrule�
\lineboxed{,,,,,,,\\,,\\,,,,,,}|�*\lineboxed[|)]\end{exercice}\idx*[|)]{boite!empilement}

\subsection{Dessiner des quadrillages}\idx*[|(]{quadrillages}
Comment parler de r�glure sans parler de quadrillage ? Car s'il est bien un domaine o� elles sont adapt�es, c'est bien celui-l�.

Mettons � profit ce que nous savons pour �crire une macro �\grid[|(], capable de dessiner des quadrillages tels que celui-ci :

\begin{centrage}
\xunit=1.5cm \yunit=1cm \mainrule=1pt \subrule=0.2pt
\leavevmode\grid{5}{4}{2}{10}
\end{centrage}

Avant d'entrer dans le vif du sujet, quel est le nombre de param�tres qu'il est n�cessaire de sp�cifier ? L'observation de ce quadrillage permet de se faire une id�e. Il faut d�finir la largeur et hauteur d'un carreau-unit� que nous stockerons dans deux registres de dimension (\verb|\xunit| et \verb|\yunit|) ainsi que l'�paisseur des lignes principales et secondaires stock�es dans deux autres registres de dimension (\verb|\mainrule| et \verb|\subrule|). Puis, il faut passer � la macro �\grid le nombre de carreaux-unit� que l'on veut horizontalement et verticalement ainsi que le nombre de subdivisions horizontales et verticales dans chaque carreau. Il semble donc naturel de construire une macro utilisant 4 registres de dimension et admettant 4 arguments.

Le quadrillage ci-dessus a �t� trac� en ex�cutant

\centrecode-\grid{5}{4}{2}{10}-

\noindent pour demander qu'il comporte 5 carreaux-unit� horizontalement, chacun divis� en 4 et 2 carreaux-unit� verticalement, chacun divis� en 10. De plus, les registres de dimension ont �t� initialis�s avec

\centrecode-\xunit=1.5cm \yunit=1cm \mainrule=1pt \subrule=0.2pt-

\subsubsection{R�glures horizontales}
Construisons la macro �\grid pas � pas et d�cidons que cette macro mettra des �l�ments dans une \idx\vbox.Nous allons dans un premier temps empiler des �l�ments dans une liste verticale pour tracer les r�glures horizontales. Il est bien entendu que l'�paisseur des r�glures ne doit pas perturber les espacements verticaux, c'est pourquoi elles doivent �tre mises dans une sous-boite de hauteur nulle. Nous allons donc d�finir l'analogue de �\clap mais pour les \idx\vbox. La macro suivante, �\vlap enferme son argument dans une boite verticale et rend la hauteur du tout �gale � \verb|0pt| :

\centrecode-\def\vlap#1{\vbox to0pt{\vss#1\vss}}-\idx*\vss

Chaque r�glure horizontale doit avoir comme largeur \verb|\xunit*#1|, que nous stockerons dans une macro pour l'utiliser ensuite. Pour que les espacements verticaux soient rigoureusement exacts, le ressort inter-ligne doit �tre neutralis� et pour cela, \idx\offinterlineskip sera appel� au d�but de la \idx\vbox. Voici un premier essai o� ne sont construites que les r�glures horizontales principales. On prend les unit�s �gales � \numprint[cm]{0.5} par souci de gain de place.

\showcode/\xunit=0.5cm \yunit=0.5cm \mainrule=0.8pt \subrule=0.2pt
\def\vlap#1{\vbox to0pt{\vss#1\vss}}��*\vlap\idx*\vss�
\catcode`@11
\def\grid#1#2#3#4{%��*\grid�
       \vbox{% empiler les �l�ments verticalement�\idx*\vbox�
               \offinterlineskip% pas de ressort d'interligne�\idx*\offinterlineskip�
               \edef\total@wd{\the\dimexpr\xunit*#1\relax}% largeur totale ds r�glures�\idx*\the\idx*\dimexpr�
               \for\ii = 1 to #3 \do1% pour chaque carreau vertical (\ii=variable muette)��*\for�
                       {\vlap{\hrule width\total@wd height\mainrule}% tracer la r�glure horizontale�\idx*\hrule�*\vlap�
                       \kern\yunit% ins�rer l'espace vertical�\idx*\kern�
                       }%
               \vlap{\hrule width\total@wd height\mainrule}% derni�re r�glure horizontale��*\vlap�
       }%
}
\catcode`@12
\setbox0\hbox{\grid{4}{}{3}{}}% range la quadrillage dans le registre no 0�\idx*\setbox\idx*\hbox�
Essai \copy0{} qui a pour
largeur=\convertunit{\wd0}{cm} cm et pour hauteur=\convertunit{\ht0}{cm} cm��*\convertunit\idx*\ht\idx*\wd�/

Pour s'assurer que les dimensions du quadrillage sont parfaitement correctes, le quadrillage a �t� plac� dans une \idx\hbox stock�e dans le registre de boite \no0\idx*{boite!\no0}. Ainsi, nous pouvons mesurer sa largeur et sa hauteur (converties en \verb|cm| avec la macro �\convertunit vue pr�c�demment) : les dimensions obtenues sont bien \numprint[cm]2 de largeur et \numprint[cm]{1.5} en hauteur qui correspondent � 4\verb|\xunit| et � 3\verb|\yunit|.
\grandsaut

Venons-en aux lignes horizontales de subdivisions. Elles seront plac�es imm�diatement \emph{sous} la position courante de la r�glure principale en cours, moyennant un ressort \idx\vss ins�r� en fin de \idx\vbox. Le code suivant illustre cette structure :

\showcode/D�but\vbox to0pt{\hbox{sous}\hbox{la ligne de base}\vss}suite�\idx*\vss�/
\grandsaut

Dans le cas pr�sent, nous placerons sous la position de la r�glure principale en cours le mat�riel suivant, r�p�t� \verb|#4|${}-{}1$ fois   :

\begin{itemize}
       \item l'espace verticale de dimension \verb|\yunit/#4|;
       \item la r�glure secondaire, enferm�e dans une �\vlap, de fa�on � ce que son �paisseur n'entre pas en ligne de compte.
\end{itemize}

\noindent Remarquons qu'il n'y a pas lieu de tester si \verb|#4|${}>1$, car la boucle �\for suivante

\centrecode-\for\jj = 2 to #4 \do 1 {<code � ex�cuter>}-

\noindent ne s'ex�cutera que si le test est vrai.

\showcode|\xunit=0.5cm \yunit=0.5cm \mainrule=0.8pt \subrule=0.2pt
\def\vlap#1{\vbox to0pt{\vss#1\vss}}��*\vlap\idx*\vss�
\catcode`@11
\def\grid#1#2#3#4{%��*\grid�
       \vbox{% empiler les �l�ments verticalement�\idx*\vbox�
               \offinterlineskip% pas de ressort d'interligne�\idx*\offinterlineskip�
               \edef\total@wd{\the\dimexpr\xunit*#1\relax}% largeur totale de la boite�\idx*\the\idx*\dimexpr�
               \edef\sub@unit{\the\dimexpr\yunit/#4\relax}% hauteur verticale de la subdivision
               \for\ii = 1 to #3 \do% pour chaque unit� verticale en partant du haut, tracer :��*\for�
                       {\vlap{\hrule width\total@wd height\mainrule}% la r�glure horizontale principale��*\vlap�
                       % et dessous, les r�glures horizontales secondaires :
                       \vbox to\z@{% dans une \vbox de hauteur nulle,�\idx*\vbox\idx*\z@�
                               \for\jj = 2 to #4 \do 1% ins�rer #4-1 fois sous la position courante :��*\for�
                                       {\kern\sub@unit % l'espace verticale�\idx*\kern�
                                       \vlap{\hrule width\total@wd height\subrule}% et la r�glure secondaire��*\vlap\idx*\vrule�
                                       }%
                               \vss% ressort qui se comprime pour satisfaire la hauteur nulle�\idx*\vss�
                       }%
                       \kern\yunit% ins�rer l'espace vertical entre r�glures principales�\idx*\kern�
                       }%
               \vlap{\hrule width\total@wd height\mainrule}% derni�re r�glure principale du bas��*\vlap�
       }%
}
\catcode`@12
\setbox0=\hbox{\grid{4}{}{3}{5}}�\idx*\setbox�
Essai \copy0{} qui a pour
largeur=\convertunit{\wd0}{cm} cm et pour hauteur=\convertunit{\ht0}{cm} cm�\idx*\wd\idx*\ht�*\convertunit�|

\subsubsection{R�glures verticales}
Pour les r�glures verticales, nous allons proc�der exactement de la m�me fa�on qu'avec les r�glures horizontales. Nous allons les tracer avant les r�glures horizontales et le tout sera enferm� dans une \idx\vbox chapeau contenant la totalit� du quadrillage.

Afin que ces r�glures verticales ne prennent aucun encombrement vertical, nous les enfermerons dans une \idx\vbox de hauteur nulle et ferons en sorte que le contenu de cette boite se place au-dessous de la plus haute position de la \idx\vbox chapeau en utilisant � nouveau cette structure :

\centrecode-\vbox to0pt{<r�glures verticales>\vss}-\idx*\vss

La totalit� des r�glures verticales sera mise dans une \idx\rlap, c'est-�-dire en d�bordement � droite de la position courante :

\centrecode-\vbox to0pt{\rlap{<r�glures verticales>}\vss}-\idx*\vss

Il est maintenant clair que, puisque la \idx\rlap a une largeur nulle, cette \idx\vbox aura toutes ses dimensions nulles. Cela signifie que toutes les r�glures verticales seront dessin�es sans que la position courante ne change.

\showcode|\mainrule=0.8pt \subrule=0.2pt
\def\vlap#1{\vbox to0pt{\vss#1\vss}}��*\vlap\idx*\vss�
\catcode`@11
\def\grid#1#2#3#4{%��*\grid�
       \vbox{% empiler les �l�ments verticalement�\idx*\vbox�
               \offinterlineskip% pas de ressort d'interligne�\idx*\offinterlineskip�
               % #################### Trac� des r�glures verticales ####################
               \vbox to\z@{% dans une \vbox de hauteur nulle�\idx*\vbox\idx*\z@�
                       \edef\total@ht{\the\dimexpr\yunit*#3\relax}% hauteur totale�\idx*\the\idx*\dimexpr�
                       \edef\sub@unit{\the\dimexpr\xunit/#2\relax}% espace entre 2 subdivisions
                       \rlap{% mettre � droite de la position sans bouger�\idx*\rlap�
                               \for\ii = 1 to #1 \do 1% pour chaque unit� horizontale��*\for�
                                       {\clap{\vrule width\dimexpr\mainrule height\total@ht}% r�glure principale�\idx*\vrule�*\clap�
                                       \rlap{% mettre � droite de la position sans bouger�\idx*\rlap�
                                               \for\jj = 2 to #2 \do 1% ins�rer #2-1 fois
                                                       {\kern\sub@unit % l'espace horizontal�\idx*\kern�
                                                       \clap{\vrule width\subrule height\total@ht}% et la r�glure verticale��*\clap\idx*\vrule�
                                                       }%
                                       }%
                                       \kern\xunit % ins�rer l'espace entre r�glures horizontales
                                       }%
                               \clap{\vrule width\mainrule height\total@ht}% derni�re r�glure principale�\idx*\vrule�*\clap�
                       }%
                       \vss% compense la hauteur=0pt de la \vbox�\idx*\vss�
               }%
               % #################### Trac� des r�glures horizontales ####################
               \edef\total@wd{\the\dimexpr\xunit*#1\relax}% largeur totale de la boite�\idx*\the\idx*\dimexpr�
               \edef\sub@unit{\the\dimexpr\yunit/#4\relax}% espace entre 2 subdivisions
               \for\ii = 1 to #3 \do 1% pour chaque carreau vertical en partant du haut :��*\for�
                       {\vlap{\hrule width\total@wd height\mainrule}% r�glure horizontale principale��*\vlap�
                       % et dessous, les r�glures secondaires :
                       \vbox to\z@{% dans une \vbox de hauteur nulle,�\idx*\vbox\idx*\z@�
                               \for\jj = 2 to #4 \do 1% ins�rer #4-1 fois sous la position courante :��*\for�
                                       {\kern\sub@unit % l'espace vertical�\idx*\kern�
                                       \vlap{\hrule width\total@wd height\subrule}% et la r�glure secondaire��*\vlap\idx*\vrule�
                                       }%
                               \vss% ressort qui se comprime pour satisfaire la hauteur nulle�\idx*\vss�
                       }%
                       \kern\yunit% ins�rer l'espace vertical entre r�glures principales�\idx*\kern�
                       }%
               \vlap{\hrule width\total@wd height\mainrule}% derni�re r�glure horizontale��*\vlap�
       }%
}
\catcode`@12
Grille 1 : \xunit=1cm \yunit=1cm \grid{5}{10}{2}{10}\smallskip�\idx*\smallskip�

Grille 2 : \xunit=0.5cm \yunit=0.5cm \grid{7}{1}{3}{1}\smallskip�\idx*\smallskip�

Grille 3 : \xunit=1.5cm \yunit=0.5cm \grid{4}{3}{3}{2}|�*\grid[|)]\idx*[|)]{r�glure}\idx*[|)]{quadrillages}

\section{R�p�tition de motifs}\label{repetition.motifs}
\subsection{\texttt{\char`\\leaders} et ses complices}\idx*[|(]{\leaders}
Venons-en maintenant � une primitive int�ressante qui a la capacit� de r�p�ter une boite autant de fois que n�cessaire pour remplir un espace donn�, que ce soit en mode horizontal\idx*{mode!horizontal} ou vertical\idx*{mode!vertical}. Cette primitive est \idx\leaders et la syntaxe pour le mode horizontal\idx*{mode!horizontal} est la suivante :

\centrecode-\leaders<boite ou r�glure>\hskip<ressort>-

\noindent La syntaxe est la m�me pour le mode vertical\idx*{mode!vertical} sauf que \idx\vskip est utilis� au lieu de \idx\hskip. En r�alit�, \idx\leaders est juste une assignation pour le \verb|<ressort>| qui sp�cifie tout simplement avec quel motif il doit �tre rempli. Car contrairement aux \idx\kern, un ressort a vocation � �tre rempli avec quelque chose ! Si \idx\leaders est absent comme cela a �t� le cas jusqu'� pr�sent, ce motif est vide ce qui conduit � des ressorts qui laissent des espaces blancs.

Int�ressons-nous au mode horizontal\idx*{mode!horizontal}, celui en grande majorit� pour lequel est utilis�e \idx\leaders. Supposons que la boite de \numprint[cm]{1.5} de long suivante

\centrecode-\hbox to1.5cm{\hss A\hss}-

\noindent doive remplir un espace de \numprint[cm]{10}. La primitive \idx\leaders va coller ces boites les unes aux autres de fa�on � remplir le plus grand espace possible. Ce collage se fera bord � bord en partant de la gauche et laissera, si la longueur � remplir n'est pas un multiple de la longueur du motif, une espace laiss�e vide � la fin. Dans le code ci-dessous, nous sp�cifions �\verb|\hbox to10cm|� pour imposer que la dimension horizontale � remplir soit de \numprint[cm]{10}. Les \idx\vrule plac�es de part et d'autre de cette \idx\hbox permettent de visualiser le d�but et la fin de cette boite :

\showcode/\vrule\hbox to10cm{\leaders\hbox to1.5cm{\hss A\hss}\hfill}\vrule�\idx*\vrule\idx*\leaders\idx*\hbox\idx*\hfill�/

Comme on peut facilement s'en assurer par calcul mental, seules 6 copies de la boites ont �t� coll�es les unes aux autres pour remplir un espace de \numprint[cm]9, laissant une espace vide de \numprint[cm]1 � la fin.

Deux variantes de cette primitive existent et permettent de r�partir l'�ventuelle espace non remplie :
\begin{itemize}
       \item avec \idx\cleaders, elle est �galement r�partie avant la premi�re et apr�s la derni�re boite r�p�t�e ;
       \item avec \idx\xleaders, elle est �galement r�partie avant la premi�re, apr�s la derni�re et entre chaque boite r�p�t�e.
\end{itemize}

Le plus visuellement compr�hensible est de d�finir cette boite �{\frboxsep=-\frboxrule \frbox{\hbox to1.5cm{\hss A\hss}}}�, de \numprint[cm]{1.5} de long et encadr�e au plus proche par ce code :

\centrecode/\frboxsep=-\frboxrule \frbox{\hbox to1.5cm{\hss A\hss}}/

\noindent et regarder les diff�rences de comportement entre les diff�rentes variantes. Pour bien visualiser l'espace de \numprint[cm]{10} � remplir, le caract�re actif �\cidx\~� a �t� programm� pour imprimer une r�glure horizontale de \verb|1em| de longueur juste avant et juste apr�s cette espace :

\showcode/\frboxsep=-\frboxrule \def~{\leavevmode\raise.75ex\hbox{\vrule height.2pt width1em}}��*\frboxsep\cidx*\~\idx*\raise\idx*\hbox\idx*\leavevmode\idx*\vrule�
~\hbox to10cm{\leaders\hbox{\frbox{\hbox to1.5cm{\hss A\hss}}}\hfill}~�\idx*\hfill\idx*\hss\idx*\leaders�*\frbox�

~\hbox to10cm{\cleaders\hbox{\frbox{\hbox to1.5cm{\hss A\hss}}}\hfill}~�\idx*\cleaders�

~\hbox to10cm{\xleaders\hbox{\frbox{\hbox to1.5cm{\hss A\hss}}}\hfill}~�\idx*\xleaders�*\frbox�/

Au lieu d'un encadrement contenant un texte, on peut aussi mettre une r�glure ou m�me plusieurs dans une boite pour faire des dessins rudimentaires :

\showcode+a) \leavevmode\hbox to10cm{\leaders\hrule\hfill}\smallskip�\idx*\leavevmode\idx*\smallskip�

b) \hbox to10cm{\leaders\hbox{\vrule height0.2pt width2.5mm \kern1.5mm}\hfill}�\idx*\leaders\idx*\leavevmode\idx*\hfill�

c) \vrule width0.2pt height1ex depth0pt % premi�re r�glure verticale
    \hbox to10cm{% puis r�p�tition de "_|"
    \leaders\hbox{\vrule width2em height0.2pt \vrule width0.2pt height1ex}\hfill}�\idx*\vrule�

d) \hbox to10cm{\leaders\hbox{%�\idx*\leaders\idx*\leavevmode�
               \vrule height.2pt width.5em% 1/2 palier bas�\idx*\vrule�
               \vrule height5pt width0.2pt% mont�e au palier haut
               \vrule height5pt depth-4.8pt width1em% palier haut
               \vrule height5pt width0.2pt% descente au palier bas
               \vrule height.2pt width.5em% 1/2 palier bas�\idx*\vrule�
               }\hfill}+

La macro \idx\hrulefill, qui remplit l'espace disponible avec une r�glure horizontale, est programm�e de la fa�on suivante dans plain-\TeX{} :

\centrecode-\def\hrulefill{\leaders\hrule\hfill}-

\noindent C'est d'ailleurs un cas o� la primitive \idx\hrule peut �tre appel�e en mode horizontal\idx*{mode!horizontal} pour produire une r�glure horizontale alors que son mode de fonctionnement est le mode vertical\idx*{mode!vertical}.\idx*[|)]{\leaders}

\subsection{Retour sur le quadrillage}
On entrevoit que la primitive \idx\leaders, de par sa propri�t� qui est d'effectuer une r�p�tition, peut nous aider � tracer un quadrillage sans faire explicitement appel � une boucle ! Pour y arriver, nous allons tout d'abord nous employer � construire un carreau-unit� avec les subdivisions ad�quates que \idx\leaders r�p�tera horizontalement et verticalement pour cr�er le quadrillage.

Commen�ons verticalement. S'il faut $n$ subdivisions dans une espace verticale de \verb|\yunit|, il faut empiler verticalement dans une boite de hauteur \verb|\yunit| :

\begin{enumerate}
       \item une r�glure horizontale d'�paisseur \verb|\mainrule| dont la dimension verticale sera forc�e � 0pt;
       \item placer autant de fois qu'il est possible ce mat�riel vertical suivant (dont la dimension est \verb|\yunit|/$n$) :
       \begin{enumerate}
               \item une espace verticale de dimension \verb|\yunit|/$n$;
               \item une r�glure horizontale d'�paisseur \verb|\subrule| dont la dimension verticale sera forc�e � 0pt;
       \end{enumerate}
       \item une espace verticale de dimension \verb|\yunit|/$n$;
       \item une r�glure horizontale d'�paisseur \verb|\mainrule| dont la dimension verticale sera forc�e � 0pt.
\end{enumerate}

Comme les composants du point \no2 prennent � chaque fois \verb|\yunit|/$n$ d'espace vertical et que les deux derniers composants prennent aussi cette espace, la r�p�tition de l'�l�ment 2 aura donc lieu $n-1$ fois.

\showcode|\mainrule=0.8pt \subrule=0.2pt
\def\carreau#1#2{% #1=nb subdiv H  #2=nb subdiv V
       \vbox to\yunit{% dans un \vbox de hauteur \yunit�\idx*\vbox�
               \offinterlineskip% pas de ressort d'interligne�\idx*\offinterlineskip�
               \vlap{\hrule height\mainrule width\xunit}% r�glure principale du haut��*\vlap�
               \leaders% r�p�ter (ici ce sera donc #2-1 fois)�\idx*\leaders�
                       \vbox to\dimexpr\yunit/#2\relax% une \vbox de hauteur \yunit/#2�\idx*\vbox\idx*\dimexpr�
                               {\vss% ressort qui va s'�tirer � \yunit/#2�\idx*\vss�
                               \vlap{\hrule height\subrule width\xunit}% r�glure de subdiv de dim 0pt
                               }\vfill�\idx*\vfill�
               \kern\dimexpr\yunit/#2\relax% derni�re espace verticale�\idx*\kern�
               \vlap{\hrule height\mainrule width\xunit}% r�glure principale du bas�\idx*\hrule�*\vlap�
       }%
}
\yunit=1cm
\leavevmode \carreau{}{4} puis \carreau{}{10}�\idx*\leavevmode�|

Pour les r�glures horizontales, nous allons proc�der de m�me apr�s voir mis tout le code pr�c�dent dans une \idx\rlap de telle sorte que son encombrement horizontal soit nul.

\showcode|\mainrule=0.8pt \subrule=0.2pt
\def\carreau#1#2{% #1=nb subdiv H  #2=nb subdiv V
       % ######## r�glures horizontales ########
       \rlap{% mettre � droite de la position sans bouger�\idx*\rlap�
               \vbox to\yunit{% dans un \vbox de hauteur \yunit
                       \offinterlineskip% pas de ressort d'interligne�\idx*\offinterlineskip�
                       \vlap{\hrule height\mainrule width\xunit}% r�glure principale du haut��*\vlap�
                       \leaders% r�p�ter (ici ce sera #2-1 fois)�\idx*\leaders�
                               \vbox to\dimexpr\yunit/#2\relax% une \vbox de hauteur \yunit/#2�\idx*\vbox\idx*\dimexpr�
                                       {\vss% ressort qui va s'�tirer � \yunit/#2�\idx*\vss�
                                       \vlap{\hrule height\subrule width\xunit}% r�glure de subdiv de dim 0pt
                                       }\vfill% ressort de \leaders�\idx*\vfill�
                       \kern\dimexpr\yunit/#2\relax% derniere espace verticale�\idx*\kern�
                       \vlap{\hrule height\mainrule width\xunit}% r�glure principale du bas�\idx*\hrule�*\vlap�
               }%
       }%
       % ######## r�glures verticales ########
       \hbox to\xunit{% dans une \hbox de longueur \xunit�\idx*\hbox�
               \clap{\vrule height\yunit width\mainrule}% r�glure principale de gauche��*\clap\idx*\vrule�
               \leaders% r�p�ter (ici ce sera #1-1 fois)�\idx*\leaders�
                       \hbox to\dimexpr\xunit/#1\relax�\idx*\dimexpr\idx*\hbox�
                               {\hss% ressort qui va s'�tirer � \xunit/#1�\idx*\hss�
                               \clap{\vrule height\yunit width\subrule}% r�glure H de dimension 0
                               }\hfill% ressort de \leaders�\idx*\hfill�
                       \kern\dimexpr\xunit/#1\relax% derni�re espace H�\idx*\kern�
                       \clap{\vrule height\yunit width\mainrule}% r�glure principale de droite�\idx*\vrule�*\clap�
       }%
}
\yunit=1cm \xunit=2cm
\leavevmode \carreau{3}{4} puis \carreau{8}{10}�\idx*\leavevmode�|

Il suffit maintenant de mettre le tout dans une \idx\hbox. Cette boite a pour exactes dimensions \verb|\xunit| et \verb|\yunit| et il ne reste plus qu'� confier � \idx\leaders le soin de la r�p�ter autant de fois horizontalement et verticalement que l'on veut de carreaux dans ces deux directions :

\begingroup
\def\carreau#1#2{% #1=nb subdiv H  #2=nb subdiv V
       % #### r�glures horizontales
       \rlap{% mettre � droite de la position sans bouger�\idx*\rlap�
               \vbox to\yunit{% dans un \vbox de hauteur \yunit�\idx*\vbox�
                       \offinterlineskip% pas de ressort d'interligne�\idx*\offinterlineskip�
                       \vlap{\hrule height\mainrule width\xunit}% r�glure principale��*\vlap\idx*\hrule�
                       \leaders% r�p�ter (ici ce sera donc #2-1 fois)�\idx*\leaders�
                               \vbox to\dimexpr\yunit/#2\relax% une \vbox de hauteur \yunit/#2�\idx*\dimexpr�
                                       {\vss% ressort qui va s'�tirer � \yunit/#2�\idx*\vss�
                                       \vlap{\hrule height\subrule width\xunit}% r�glure de subdiv de dim 0pt
                                       }\vfill% ressort de \leaders�\idx*\vfill�
                       \kern\dimexpr\yunit/#2\relax% derniere espace verticale�\idx*\kern�
                       \vlap{\hrule height\mainrule width\xunit}% r�glure principale��*\vlap�
               }%
       }%
       % #### r�glures verticales
       \hbox to\xunit{% dans une \hbox de longueur \xunit�\idx*\vbox�
               \clap{\vrule height\yunit width\mainrule}% r�glure principale��*\clap\idx*\vrule�
               \leaders% r�op�ter (ici ce sera donc #1-1 fois)�\idx*\leaders�
                       \hbox to\dimexpr\xunit/#1\relax�\idx*\hbox�
                               {\hss% ressort qui va s'�tirer � \xunit/#1�\idx*\hss�
                               \clap{\vrule height\yunit width\subrule}% r�glure H de dimension 0��*\clap�
                               }\hfill% ressort de \leaders�\idx*\hfill�
                       \kern\dimexpr\xunit/#1\relax% derni�re espace H�\idx*\kern�
                       \clap{\vrule height\yunit width\mainrule}% r�glure principale�\idx*\vrule�*\clap�
       }%
}
\showcode|\mainrule=0.8pt \subrule=0.2pt
\def\grid#1#2#3#4{%��*\grid�
       \vbox to#3\yunit{% dans une boite verticale de hauteur #3*\yunit�\idx*\vbox�
               \leaders% r�p�ter verticalement�\idx*\leaders�
                       \hbox to#1\xunit{% une boite de longueur #1*\xunit
                               \leaders% dans laquelle se r�p�te horizontalement�\idx*\leaders�
                                       \hbox{\carreau{#2}{#4}}% le carreau de largeur \xunit
                               \hfill}%�\idx*\hfill�
               \vfill�\idx*\vfill�
       }%
}
Grille 1 : \xunit=1cm \yunit=1cm \grid{5}{10}{2}{10}\smallskip�\idx*\smallskip�

Grille 2 : \xunit=0.5cm \yunit=0.5cm \grid{7}{1}{3}{1}\smallskip�\idx*\smallskip�

Grille 3 : \xunit=1.5cm \yunit=0.5cm \grid{4}{3}{3}{2}|
\endgroup

Bien que le r�sultat soit strictement identique, la fa�on de tracer le quadrillage avec \idx\leaders comme ci-dessus est tr�s diff�rente de celle employ�e pr�c�demment avec la boucle �\for. En effet, la m�thode avec \idx\leaders est beaucoup plus �laborieuse� puisqu'il s'agit d'une b�te r�p�tition d'un �l�ment. Le r�sultat est trompeur pour l'\oe il, car la r�p�tition horizontale et verticale de cet �l�ment donne l'illusion que les r�glures horizontales ou verticales sont trac�es en un coup alors qu'il n'en est rien. De plus, toutes les r�glures principales communes � deux carreaux-unit� adjacents sont m�me superpos�es et sont donc trac�es deux fois. Personne ne tracerait un quadrillage � la main de cette fa�on sur une feuille de papier ! � l'inverse, la m�thode avec �\for b�tissait le quadrillage de fa�on plus globale puisque les r�glures avaient la dimension maximale et �taient effectivement trac�es en un coup, comme on le ferait spontan�ment � la r�gle et au crayon.

\chapter{Fichiers : lecture et �criture}\idx*[|(]{fichier}
\section{Lire un fichier}\idx*[|(]{fichier!lecture}
\subsection{La primitive \texttt{\char`\\ input}}\idx*[|(]\input
\TeX{} peut � lire un fichier �, c'est-�-dire qu'il peut lire le contenu du fichier, exactement comme il le fait lorsqu'il lit le code source. Pour cela, on utilise la syntaxe\footnote{Il est peut-�tre utile de signaler que \LaTeX{}, aussi incroyable que cela puisse paraitre, franchit un interdit en red�finissant la primitive \texttt{\string\input} pour en faire une macro (non d�veloppable). Fort heureusement, la primitive est sauvegard�e par \texttt{\string\let} dans la s�quence de contr�le \texttt{\string\@@input}.} :

\centrecode-\input <nom d'un fichier>-

\noindent Lorsque \TeX{} s'attend � lire le nom d'un fichier, le d�veloppement maximal se met en place. Le nom du fichier s'�tend jusqu'au premier espace rencontr� (et cet espace sera absorb�) ou jusqu'� la premi�re primitive non d�veloppable : mettre un espace ou un \idx\relax apr�s la fin d'un nom de fichier est donc une bonne habitude � prendre.

La primitive \idx\jobname se d�veloppe en le nom du fichier � maitre � en cours de compilation. Le fichier � maitre � est le fichier de plus haut niveau, celui qui n'a �t� appel� par aucun \idx\input.  Le nom cr�� par \idx\jobname se compose de caract�res de catcode 12\idx*{catcode!12 (autre)} et ne comporte pas l'extension du fichier, c'est-�-dire le �\verb|.|� et les caract�res qui le suivent.

Le fichier lu par \idx\input peut lui aussi contenir la primitive \idx\input, et ainsi de suite r�cursivement dans des limites raisonnables. Une fois que la fin du fichier est atteinte ou que la primitive \verb|\endinput| est rencontr�e, \TeX{} cesse la lecture du fichier et la reprend dans fichier parent o� il s'�tait interrompu.

\begin{regle}
Lorsque \TeX{} lit le code source, on peut faire lire � \TeX{} le contenu d'un fichier. La lecture se fera comme se fait celle du code source et tout se passe donc comme si l'int�gralit� du contenu du fichier �tait ins�r�e dans le code source � l'endroit o� est rencontr� :

\centrecode-\input <nom de fichier>-

Si le \verb|<nom de fichier>| ne sp�cifie pas d'extension, \TeX{} rajoute �\verb|.tex|�.

La lecture du fichier s'arr�te lorsque la fin du fichier est atteinte ou lorsque la primitive \verb|\endinput| est atteinte.
\end{regle}

\subsection{\texttt{\char`\\ input} et ses secrets}\label{input.secrets}
Examinons maintenant les autres aspects bien plus \TeX niques de la primitive \idx\input. Cette section, assez ardue, peut �tre saut�e lors d'une premi�re lecture.

Tout d'abord, la primitive \idx\input est d�veloppable lorsqu'on la 1-d�veloppe, tout se passe comme si \TeX{} d�tournait sa t�te de lecture pour aller lire la totalit� du contenu du fichier. Il faut signaler que la totalit� du fichier est lue selon le r�gime de catcode en vigueur au moment du 1-d�veloppement. De la m�me fa�on qu'il le fait lorsqu'il lit du code source, \TeX{} ins�re le caract�re de code \idx\endlinechar � la fin de chaque ligne du fichier, y compris la derni�re.

Plusieurs choses assez \TeX niques se passent � la fin d'un fichier :

\begin{enumerate}
       \item avant la fin du fichier, \TeX{} ins�re le contenu de \idx\everyeof. Cette primitive a un comportement identique � celui d'un registre de tokens et elle est vide par d�faut;
       \item juste apr�s le code ins�r� par \idx\everyeof, \TeX{} ex�cute une routine interne.
\end{enumerate}

Cette routine interne est en r�alit� un test auquel proc�de \TeX{} : il v�rifie que l'endroit o� il se trouve est compatible avec le statut \idx\outer\footnote{On peut le constater dans le code source �\texttt{tex.web}� du programme \texttt{tex} � la section \no362, le test �\texttt{check\_outer\_validity}� est effectu�.}. Avant de poursuivre, il faut d�finir ce qu'est ce statut : il concerne normalement les macros qui peuvent �tre d�finies comme �tant �\idx\outer�.

\label{outer}\begin{regle}
Lorsque la primitive \idx\outer pr�c�de la d�finition d'une macro, cette derni�re ne pourra pas se situer dans les endroits o� \TeX{} lit du code � � grande vitesse �\idx*{lecture � grande vitesse}, � savoir :
\begin{itemize}
       \item le texte de remplacement ou le \idx{texte de param�tre} lors de la d�finition d'une macro ;
       \item le code situ� dans les branches d'un test;
       \item le pr�ambule d'un alignement initi� par \idx\halign ou \idx\valign.
\end{itemize}
\end{regle}

Si une telle macro se trouve dans ces endroits interdits, un message d'erreur sera �mis et la compilation stopp�e :

\errcode/\outer\def\foo{Bonjour}
\def\bar{\foo}/{! Forbidden control sequence found while scanning definition of \string\bar.}

Une action peu connue de \idx\noexpand\verb|<token>|, lorsque \idx\noexpand est d�velopp�, est de d�sactiver pour le \verb|<token>| le test qui v�rifie si ce \verb|<token>| est \idx\outer\footnote{Cela est expliqu� � la section \no369 de \texttt{tex.web} par \textsc{Knuth} lui-m�me : �Comme des macros {\string\outer} peuvent se pr�senter ici, on doit aussi r�initialiser [� "\texttt{normal}"] le \texttt{scanner\_statut} temporairement.�}. On peut donc l'utiliser pour enfreindre la r�gle pr�c�dente et mettre une macro \idx\outer dans le texte de remplacement d'une autre macro :

\showcode/\outer\def\foo{Bonjour}�\idx*\outer�
\expandafter\def\expandafter\bar\expandafter{\noexpand\foo}�\idx*\noexpand�
\meaning\bar�\idx*\meaning�

\edef\baz{\noexpand\foo}�\idx*\noexpand�
\meaning\baz/

Revenons au test � la fin du fichier : comme il v�rifie que l'endroit o� il se trouve est compatible avec \idx\outer, il communique � la fin du fichier le statut \idx\outer. Pour d�sactiver le test, nous allons appliquer la m�me m�thode qu'avec une macro \idx\outer, c'est-�-dire le faire pr�c�der de la primitive \idx\noexpand.

\begin{regle}
La fin d'un fichier a le statut \idx\outer.

Pour permettre que la fin d'un fichier se situe dans un endroit normalement interdit � ce statut, il faut placer la primitive \idx\noexpand juste avant la fin du fichier, soit en l'�crivant explicitement, soit via \idx\everyeof avec l'assignation

\centrecode-\everyeof{\noexpand}-\idx*\everyeof

\noindent et faire en sorte de d�velopper ce \idx\noexpand.
\end{regle}

D�velopper le \idx\noexpand rend tr�s contraignante et quasi impossible la d�finition d'une macro dont le texte de remplacement serait le contenu d'un fichier. En effet, pour forcer ce d�veloppement \emph{avant} que la d�finition de la macro ne se fasse, il faudrait la d�finir avec \idx[|etc]\edef\forbidindex\edef{} selon ce sch�ma :

\centrecode-\begingroup
\everyeof{\noexpand}�\idx*\noexpand�
\global\edef\<macro>{\input<nom de fichier> }
\endgroup-\idx*\global\idx*\input

Cette d�finition est tr�s peu satisfaisante, car la primitive \idx\edef implique que le contenu du fichier est d�velopp� au maximum ce qui, sauf cas tr�s particulier, n'est pas ce qui est recherch�. De plus, elle rend la d�finition globale puisqu'un groupe semi-simple a �t� ouvert pour limiter la port�e de la modification de \idx\everyeof.

\label{input.dans.macro}Heureusement, nous pouvons bien mieux faire. L'id�e est d'ins�rer un d�limiteur (ici \verb|\eof@nil|) en fin de fichier via \idx\everyeof. Ce d�limiteur sera captur� par une macro auxiliaire � argument d�limit� qui sera d�s lors capable de savoir o� se trouve la fin du fichier et affecter � une macro ce qui se trouve dans ce fichier avant ce d�limiteur. Toute cette man\oe uvre suppose que le fichier ne contient pas \verb|\eof@nil|.

Supposons par exemple que le fichier �\texttt{test.txt}� contient :

\centrecode-Programmer en \TeX{} est   facile

et utile-

Voici comment programmer une macro �*\filedef[|(]

\centrecode-\filedef\<macro>{<nom du fichier>}-
\immediate\openout\wtest=test.txt
\exactwrite\wtest|Programmer en \TeX{} est   facile

et utile|%
\immediate\closeout\wtest

\noindent qui d�finit une \verb|\<macro>| dont le texte de remplacement est le contenu du fichier :

\showcode/\catcode`\@11
\long\def\filedef#1#2{%��*\filedef\idx*\long�
       \begingroup
               \let\input\@@input% <- utilisateurs de latex uniquement�\idx*\input\idx*\@@input\idx*[|etc]\let\forbidindex\let�
               \everyeof{\eof@nil\noexpand}% ins�re "\eof@nil\noexpand" � la fin du fichier�\idx*\everyeof\idx*\noexpand�
               \expandafter\filedef@i\expandafter#1% d�veloppe \input #2�\defline\ccc�
                       \expandafter\relax\input #2�\defline\aaa�
}
\long\def\filedef@i#1#2\eof@nil{%�\idx*\long�
       \endgroup
       \expandafter\def\expandafter#1\expandafter{\gobone#2}% mange le \relax�\defline\bbb�
}
\catcode`\@12
\filedef\foo{test.txt}
\meaning\foo/

La ligne �\verb|\let\input\@@input|� redonne � \idx\input son statut de primitive et annule la red�finition effectu�e par \LaTeX\footnote{Ce livre a �t� compil� en utilisant le format \LaTeX.}. Il est bien �vident que les utilisateurs d'autres formats ne doivent pas �crire cette ligne.

Ensuite, � la ligne \no\aaa, un \idx\relax a �t� ins�r� avant le d�veloppement de \idx\input. Ceci nous assure que l'argument d�limit� \verb|#2| de \verb|\filedef@i| ne serait pas d�pouill� de ses accolades si jamais le contenu du fichier �tait constitu� d'un texte entre accolades. Ce \idx\relax est mang� � la ligne \no\bbb{} par le \verb|\gobone| avant que la d�finition ne soit faite.

L'important est de comprendre qu'une fois le \idx\input 1-d�velopp� par le pont d'\idx\expandafter et en tenant compte du contenu de \idx\everyeof, les lignes \nos\ccc{} et \number\numexpr\ccc+1\relax{} deviennent :

\centrecode-\filedef@i#1\relax<contenu du fichier lu par \input>\eof@nil\noexpand<EOF>-

\noindent La macro \verb|\filedef@i|, qui ne lit que ce qui se situe jusqu'au \verb|\eof@nil|, ne verra jamais la fin du fichier \verb|<EOF>|. Le but recherch� est atteint : le \verb|<EOF>| est pr�c�d� d'un \idx\noexpand, et ce \idx\noexpand, en �tant ex�cut� apr�s que \verb|\filedef@i| ait fait son travail, rendra \verb|<EOF>| compatible avec le statut \idx\outer.\idx*[|)]\input�*\filedef[|)]

\section{Lire dans un fichier}
� Lire un fichier � n'a pas la m�me signification que � lire \emph{dans} un fichier � qui sous-entend que l'on peut lire, contr�ler ce qu'on lit et donc reprendre la main. Pour fonctionner selon ce mode, \TeX{} dispose de 16 canaux d'entr�e, num�rot�s de 0 � 15, chacun correspondant � un flux de lecture. Comme pour les boites, les compteurs, les dimensions et les registres de tokens, plain-\TeX{} fournit la macro \idx\newread\verb|\<macro>| qui assigne\footnote{Cette macro fonctionne comme son homologue \texttt{\string\newbox}. Comme il n'existe pas de primitive \texttt{\string\readdef}, la macro est d�finie par la primitive \texttt{\string\chardef}.} � la \verb|\<macro>| un entier correspondant � un canal de lecture disponible.

\begin{regle}
\relax\TeX{} dispose de 15 canaux de lecture portant les num�ros de 0 � 15.

On demande l'allocation d'un canal de lecture par

\centrecode-\newread\<macro>-

et ce faisant, la \verb|\<macro>| devient �quivalente � un \verb|<nombre>|, qui est un num�ro de canal libre. Un \verb|<canal>| est donc un \verb|<nombre>| explicitement �crit ou une macro d�finie avec \idx\newread.
\medbreak

Avant de lire dans un fichier, on doit d'abord lier un \verb|<canal>| � un fichier avec\idx*\openin :

\centrecode-\openin<canal>= <nom du fichier>-

\noindent Si aucune extension n'est pr�cis�e au \verb|<nom du fichier>|, \TeX{} rajoute �\verb|.tex|�. Le signe \verb|=| et l'espace qui le suit sont optionnels. Lorsque \TeX{} lit le \verb|<nom du fichier>|, il entre dans une phase de d�veloppement maximal et si ce nom est suivi d'un espace, cet espace est absorb�.

Tout canal ouvert doit �tre ferm� et donc, apr�s avoir fait les op�rations de lecture, il convient d'ex�cuter \idx\closein\verb|<canal>| pour d�solidariser le \verb|<canal>| du fichier qui lui avait �t� attach� avec \idx\openin.
\end{regle}

Le test \tidx{ifeof}\verb|<canal>| teste si la lecture du fichier li� au \verb|<canal>| est arriv�e � la fin du fichier. Employ� juste apr�s avoir li� un flux � un fichier via \idx\openin, le test \verb|\ifeof<canal>| sera vrai uniquement si le fichier sp�cifi� n'existe pas. Voici donc comment b�tir une macro �\iffileexists :

\showcode/�\string\newread\string\rtest\idx*\newread�% canal de lecture employ� dans tout ce chapitre
\def\iffileexists#1#2{% #1=canal de lecture  #2=nom du fichier��*\iffileexists�
       \openin#1=#2�\idx*\openin�
       \ifeof#1% le fichier n'existe pas�\tidx*{ifeof}�
               \closein#1�\idx*\closein�
               \expandafter\secondoftwo% renvoyer faux��*\secondoftwo[|etc]\forbidindex\secondoftwo�
       \else
               \closein#1
               \expandafter\firstoftwo% sinon renvoyer vrai��*\firstoftwo[|etc]\forbidindex\firstoftwo�
       \fi
}
a) \iffileexists\rtest{test.txt}{vrai}{faux}\qquad
b) \iffileexists\rtest{foobar.txt}{vrai}{faux}��*\iffileexists�/

Dans tout cet exemple, nous avons demand� l'allocation d'un \verb|<canal>| avec � \idx\newread\verb|\rtest| � et d�sormais, nous utiliserons le canal de lecture \no\verb|\rtest| dans tous les exemples.
\grandsaut

Un fichier peut-�tre lu par plusieurs canaux simultan�ment. Cela signifie que si le besoin s'en fait sentir, on peut positionner des t�tes de lecture dans un fichier � plusieurs endroits, chacune pouvant lire le fichier ind�pendamment des autres.

\begin{regle}
Lorsqu'un \verb|<canal>| de lecture est ouvert et li� � un fichier, \TeX{} peut lire des \emph{lignes} dans ce fichier les unes apr�s les autres, et assigner la ligne lue � une macro. On utilise la syntaxe\idx*\read

\centrecode-\read\<canal> to \<macro>-

\noindent o� le mot-cl� �to� est obligatoire et �ventuellement suivi d'espaces optionnels.

Ceci a pour effet de placer dans le texte de remplacement de la \verb|\<macro>| tout ce qu'il y a dans la ligne en cours :

\begin{itemize}
       \item les accolades doivent �tre �quilibr�es dans la ligne en cours. Si elles ne le sont pas, \TeX{} lit autant de lignes que n�cessaire pour qu'elles le soient. Si la fin du fichier est atteinte sans que l'�quilibrage des accolades ne soit r�alis�, une erreur de compilation surviendra;
       \item une fois l'�quilibrage des accolades atteint, la primitive \idx\read lit tout ce qui s'�tend jusqu'� la �marque de \idx{fin de ligne}� (voir page~\pageref{marque.fin.ligne});
       \item les tokens dans le texte de remplacement de la \verb|\<macro>| tiennent compte du r�gime de catcode en vigueur lorsque \idx\read est ex�cut�e; \idx\read effectue donc une � tok�nisation�, c'est-�-dire la transformation d'\idx{octet}s bruts en tokens;
       \item le caract�re de code \idx\endlinechar est ins�r� � la fin du texte de remplacement de la\verb|\<macro>|;
       \item l'assignation est globale si \idx\read est pr�c�d� de \idx\global.
\end{itemize}

La primitive de \idx\eTeX{}\idx\readline, dont la syntaxe est

\centrecode-\readline\<canal> to \<macro>-

\noindent agit comme \idx\read sauf qu'elle ins�re dans le texte de remplacement de la \verb|\<macro>| tous les tokens lus dans la ligne (y compris le caract�re de code \idx\endlinechar). L'espace aura le catcode 10\idx*{catcode!10 (espace)} et tous les autres caract�res le catcode 12\idx*{catcode!12 (autre)}.
\end{regle}

Pour fixer les id�es, si le canal \no\verb|\rtest| est li� � un fichier et que la ligne suivante � lire dans ce fichier est :

\centrecode-Programmer en \TeX{} est facile-

\noindent Si l'on �crit �\verb-\read\rtest to \foo-�, tout se passe comme si on avait fait l'assignation d'une macro sans argument :

\centrecode-\def\foo{Programmer en \TeX{} est facile }-

\noindent Il est important de noter que l'espace en fin de texte provient du caract�re de code \idx\endlinechar : celui-ci �tant par d�faut �\verbidx*[ (retour charriot)]{^^M}\verb|^^M|� de catcode \number\catcode`\^^M {}\idx*{catcode!5 (retour charriot)}, il est lu comme un espace comme le stipule la r�gle page~\pageref{regle.catcode5}. Pour mettre ce comportement en �vidence dans l'exemple ci-dessous, le fichier \verb|filetest.txt| contiet :
\immediate\openout\wtest= filetest.txt
\exactwrite\wtest|Programmer en \TeX{} est   facile

et utile|%
\immediate\closeout\wtest

\centrecode-Programmer en \TeX{} est   facile

et utile-

Notons qu'il y a 3 espaces entre les mots � est � et � facile � et regardons ce que donne le code suivant :

\showcode|\openin\rtest =filetest.txt�\idx*\openin�
\read\rtest to \foo% lit la premi�re ligne�\idx*\read�
1) Signification : \meaning\foo.\par% signification de ce qui a �t� lu�\idx*\meaning�
1) Ex�cution : \foo\par
\read\rtest to \foo% lit la deuxi�me ligne
2) Signification : \meaning\foo.\par
2) Ex�cution : \foo\par
\read\rtest to \foo% lit la derni�re ligne�\idx*\read�
3) Signification : \meaning\foo.\par�\idx*\meaning�
3) Ex�cution : \foo
\closein\rtest�\idx*\closein�|

Les points apr�s chaque \idx\meaning\verb|\foo| sont ici destin�s � mettre en �vidence l'espace en fin de texte de remplacement.

Voici le m�me exemple, cette fois-ci avec la primitive \idx\readline :

\showcode|\openin\rtest =filetest.txt�\idx*\openin�
\readline\rtest to \foo% lit la premi�re ligne�\idx*\readline�
1) Signification : \meaning\foo.\par% signification de ce qui a �t� lu�\idx*\meaning�
1) Ex�cution : \foo\par
\readline\rtest to \foo% lit la deuxi�me ligne
2) Signification : \meaning\foo.\par
2) Ex�cution : \foo\par
\readline\rtest to \foo% lit la derni�re ligne�\idx*\readline�
3) Signification : \meaning\foo.\par�\idx*\meaning�
3) Ex�cution : \foo
\closein\rtest�\idx*\closein�|

Une premi�re question se pose naturellement : d'o� viennent les virgules que l'on observe � la fin du texte de remplacement de \verb|\foo| ? Elles sont la preuve que le caract�re de code \idx\endlinechar, plac� en fin de ligne, a �t� d�tok�niz� par \idx\readline pour devenir un inoffensif caract�re de catcode 12\idx*{catcode!12 (autre)}. On voit une virgule car \idx\endlinechar a pour valeur \number\endlinechar{} et que le caract�re ayant ce code dans la \idx{fonte} utilis�e est la virgule :

\showcode/Valeur de \string\endlinechar = \number\endlinechar\par�\idx*\string\idx*\number\idx*\endlinechar�
Caract�re correspondant : << \char\endlinechar{} >>�\idx*\char�/

Le second point qui peut surprendre est qu'au premier cas, le texte de remplacement de \verb|\foo| contient \emph{tous les espaces} (ils sont 3) entre les mots �est� et �facile�, alors qu'un seul �tait lu par \idx\read. La subtile diff�rence entre \idx\read et \idx\readline est que cette derni�re ignore les catcodes en cours et ins�re dans le texte de remplacement de la macro \emph{tous} les caract�res lus dans la ligne; elle ins�re donc \emph{tous} les espaces, en leur donnant un catcode de 10.

\begin{exercice}
Proposer une m�thode pour que la macro \idx\read ne lise que ce qui se trouve dans la ligne courante, \emph{sans} y ajouter le caract�re de code \idx\endlinechar.

Appliquer cette m�thode pour �crire une macro �\xread[|(] qui agit de la m�me fa�on que \idx\read avec la m�me syntaxe :

\centrecode|\xread<canal> to \<macro>|

mais qui place dans le texte de remplacement de la \verb|\<macro>| le contenu de la ligne sans le caract�re de code \idx\endlinechar.
\solution
Il suffit d'op�rer localement et d�finir le \idx\endlinechar � $-1$ et utiliser un \idx\global pour que la
\verb|\<macro>| survive � la fermeture du groupe :

\showcode|\openin\rtest =filetest.txt�\idx*\openin�
Ligne 1 : {\endlinechar=-1 \global\read\rtest to \foo}% lit la premi�re ligne�\idx*\endlinechar\idx*\global\idx*\read�
\meaning\foo.\par% donne ce qui a �t� lu�\idx*\meaning�
Ligne 2 : {\endlinechar=-1 \global\read\rtest to \foo}% lit la deuxi�me ligne
\meaning\foo.\par
Ligne 3 : {\endlinechar=-1 \global\read\rtest to \foo}% lit la derni�re ligne�\idx*\endlinechar\idx*\global\idx*\read�
\meaning\foo.�\idx*\meaning�
\closein\rtest�\idx*\closein�|

Contrairement � l'exemple pr�c�dent, comme le caract�re de code \idx\endlinechar n'est pas ins�r� � la fin des lignes, la seconde ligne est bien lue comme �tant vide.

Pour la macro \verb|\xread|, nous n'allons pas utiliser de \idx\global car il est toujours plus s�r de se passer, lorsque c'est possible, d'assignations globales qui provoquent des effets de bord difficiles � maitriser. Nous allons tout d'abord sauvegarder  dans la macro \verb|\restoreendlinechar| le code qui permet de restaurer \idx\endlinechar. Cette macro aura comme texte de remplacement

\centrecode-\endlinechar=<valeur actuelle de \endlinechar>-

Toute la difficult� vient ensuite des espaces optionnels qui se trouvent apr�s le mot-cl� �\verb|to|�. En effet, si nous d�clarons la macro �\xread ainsi

\centrecode-\def\xread#1to#2{<code � d�finir>}-

\noindent rien ne permet d'affirmer que l'argument \verb|#2| sera la \verb|\<macro>| : si des espaces optionnels sont �crits apr�s �\verb|to|�, alors \verb|#2| sera un espace. Il va donc falloir tester l'argument \verb|#2| et ne le prendre en compte que lorsqu'il sera une s�quence de contr�le, ce qui suppose la mise en place d'une macro r�cursive. Pour mener � bien le test, nous mettrons en \oe uvre la macro �\ifcs programm�e � la page~\pageref{ifcs.la.vraie}.

\showcode/\def\xread#1to#2{%
       \ifcs{#2}% si #2 est une s�quence de contr�le
               {\edef\restoreendlinechar{\endlinechar=\the\endlinechar}%
               \endlinechar=-1 % supprime le caract�re mis en fin de ligne
               \read#1to#2% lit la ligne et l'assigne � la macro #2
               \restoreendlinechar\relax% restaure le \endlinechar
               }% si #2 n'est pas une s�quence de contr�le,
               {\xread#1to}% ignorer #2, et recommencer
}

\openin\rtest =filetest.txt�\idx*\openin�
Ligne 1 : \xread\rtest to \foo% lit la premi�re ligne
\meaning\foo.\par% donne ce qui a �t� lu�\idx*\meaning�
Ligne 2 : \xread\rtest to \foo% lit la deuxi�me ligne
\meaning\foo.\par
Ligne 3 : \xread\rtest to \foo% lit la derni�re ligne
\meaning\foo.�\idx*\meaning�
\closein\rtest�\idx*\closein�/

Une premi�re remarque consiste � dire que la syntaxe de �\xread n'est \emph{pas exactement identique} � celle de \idx\read. En effet, la macro r�cursive �\xread ignore les arguments \verb|#2| tant qu'ils ne sont pas une s�quence de contr�le. L'appel farfelu suivant est donc tout � fait valide :

\centrecode-\xread\rtest toW a aZcd 1 2345\foo-

Mais surtout, il existe une m�thode bien plus �l�gante pour programmer �\xread, non r�cursive, ayant exactement la m�me syntaxe que \idx\read, mais qui fait intervenir la primitive \idx\afterassignment que nous verrons plus tard (voir page~\pageref{afterassignment}). Le code est donn� � titre indicatif :

\showcode|\def\xread{% doit �tre suivie de "<nombre> to \<macro>"
       \edef\restoreendlinechar{\endlinechar=\the\endlinechar}%�\idx*\endlinechar\idx*\the�
       \endlinechar=-1 % neutralise \endlinechar
       \afterassignment\restoreendlinechar% apr�s l'assignation, restaurer \endlinechar�\idx*\afterassignment�
       \read% attend <nombre> to \<macro> pour effectuer l'assignation�\idx*\read�
}
\catcode`\@12

\openin\rtest =filetest.txt�\idx*\openin�
Ligne 1 : \xread\rtest to \foo% lit la premi�re ligne
\meaning\foo.\par% donne ce qui a �t� lu�\idx*\meaning�
Ligne 2 : \xread\rtest to \foo% lit la deuxi�me ligne
\meaning\foo.\par
Ligne 3 : \xread\rtest to \foo% lit la derni�re ligne
\meaning\foo.�\idx*\meaning�
\closein\rtest�\idx*\closein�|�*\xread[|)]
\end{exercice}

\subsection{Faire une recherche dans un fichier}
Envisageons maintenant un cas pratique et imaginons qu'une liste de fournitures soit contenue dans un fichier �\verb|founitures.txt|� dont le contenu est le suivant :

\immediate\openout\wtest= fournitures.txt
\immediate\write\wtest{Ref,Item,Prix,Fournisseur^^J%
1201a,article 1,25.90,\noexpand\TeX{} marchand ^^J%
4562u,article 2,120,fournisseur 1^^J%
1721d,article 3,57.10,fournisseur 2}%
\immediate\closeout\wtest
\centrecode|Ref,Item,Prix,Fournisseur
1201a,article 1,25.90,\TeX{} marchand
4562u,article 2,120,fournisseur 1
1721d,article 3,57.10,fournisseur 2
<etc>|

On remarque que la premi�re ligne du fichier n'est pas � proprement parler une ligne de donn�es, elle indique le nom des champs qui composent les lignes suivantes.

Supposons que ce fichier soit dans le m�me r�pertoire\footnote{Ou qu'un lien symbolique vers ce fichier soit pr�sent dans le r�pertoire de compilation.} que le fichier maitre et que nous souhaitions chercher dans ce fichier une ligne par sa r�f�rence, c'est-�-dire par ce qui est contenu dans le premier champ. Le but est de mettre au point une macro �\searchitem appel�e de cette fa�on

\centrecode-\searchitem<canal>{fournitures.txt}{1721d}\foo-�*\searchitem

\noindent de telle sorte que la ligne o� se trouve le premier champ �\verb|1721d|� soit trouv�e. La macro purement d�veloppable \verb|\foo|\verb|{<champ>}| sera cr��e o� son argument pr�cisera de quel \verb|<champ>| on souhaite obtenir la valeur. Par exemple,

\begin{centrage}\small
       \begin{tabular}{r@{\quad affiche \quad}l}
               \verb|\foo{ref}|&1721d\\
               \verb|\foo{item}|&article 3\\
               \verb|\foo{prix}|&57.10\\
               \verb|\foo{fournisseur}|&fournisseur 2
       \end{tabular}
\end{centrage}

La macro \verb|\foo| est ici prise pour l'exemple, mais naturellement, le choix du nom de cette macro est � la convenance de l'utilisateur.

Fixons-nous trois contraintes suppl�mentaires :

\begin{itemize}
       \item si le fichier n'existe pas ou si la r�f�rence cherch�e n'existe pas, la macro \verb|\foo| d�finie doit �tre \idx\let-�gale � \verb|\gobone|. De cette fa�on, elle absorbera son argument et ne produira aucun affichage;
       \item si un champ n'existe pas, rien ne doit �tre affich�. Par exemple, \verb|\foo{truc}| ne doit produire aucun affichage;
       \item lors de la recherche, toute ligne vide doit �tre ignor�e.
\end{itemize}

La premi�re chose � faire va �tre d'initialiser la macro \verb|\foo| (argument \verb|#4|) sera initialis�e � \verb|\gobone|. Ensuite, la premi�re ligne du fichier sera lue, ses champs seront parcourus avec �\doforeach afin de stocker leur nom �crit en lettres minuscules dans une macro \verb|\fieldname<i>| ou \verb|<i>| est le num�ro du champ.

Par la suite, nous pourrons commencer � lire les lignes de donn�es : chaque ligne sera envoy�e � une macro auxiliaire \verb|\test@field| charg�e d'examiner leurs champs. Le premier champ de la ligne en cours sera compar� � celui qui est recherch� et si le test est positif, il incombera � la macro \verb|\test@filed| de proc�der aux assignations n�cessaires des macros

\begin{itemize}
       \item \verb|\foo.<nom du champ 1>|%{\ttfamily\textbackslash\boxtoken{foo.\codeelement{nom du champ 1}}}
       \item \verb|\foo.<nom du champ 2>|{\ttfamily\textbackslash\boxtoken{foo.\codeelement{nom du champ 2}}}
       \item etc
\end{itemize}

\noindent chacune \verb|\let|-�gale � \verb|\fieldname<i>|.

Enfin, la macro purement d�veloppable \verb|\foo|, prenant comme argument un \verb|<champ>|, sera cr��e. Elle testera avec \tidx{ifcsname} si la macro \verb|\foo.<champ>| existe, auquel cas elle formera cette macro via \idx\csname.

\showcode|\def\macroname{% se d�veloppe en le nom de la macro qui suit sans ��*\macroname�
              % le caract�re d'�chappement
       \ifnum\escapechar>-1 % si le caract�re d'�chappement est positif�\idx*\escapechar�
               \ifnum\escapechar<256 % et inf�rieur � 256, d�velopper les 2 "\fi"
                       \expandafter\expandafter\expandafter\expandafter% et le "\string", puis
                       \expandafter\expandafter\expandafter\gobone% manger le "\" avec \gobone
               \fi
       \fi
       \string% doit �tre suivi d'une macro�\idx*\string�
}
\catcode`\@11
\newcount\field@cnt
\def\searchitem#1#2#3#4{% #1= canal  #2=nom fichier #3=r�f�rence  #4=macro � d�finir��*\searchitem�
       \let#4\gobone% pour l'instant, #4=\gobone
       \openin#1=#2\relax�\idx*\openin�
       \unless\ifeof#1% si le fichier existe�\tidx*{unless}\tidx*{ifeof}�
               \lowercase{\def\sought@firstfield{#3}}% stocke le 1er champ � chercher�\idx*\lowercase�
               \edef\macro@name{\macroname#4}% nom de la macro sans "\"��*\macroname�
               \xread#1 to \current@line% lire la premi�re ligne��*\xread�
               \field@cnt=0 % initialiser le compteur de champs
               % ################ sauvegarde du nom des champs ################
               \expsecond{\doforeach\current@field\in}\current@line% pour chaque champ��*\expsecond�
                       {\advance\field@cnt1 % incr�menter le compteur de champs�\idx*\advance�
                       \lowercase\expandafter{% e texte de remplacement de \current@field en minuscule�\idx*\lowercase�
                               \expandafter\def\expandafter\current@field\expandafter{\current@field}%
                       }%
                       % sauvegarder chaque champ de la 1re ligne (qui sont les intitul�s) dans une macro
                       \letname{fieldname\number\field@cnt}=\current@field��*\letname�
                       }%
               \edef\field@num{\number\field@cnt}% nombre de champs
               % ################ lecture des lignes de donn�es ################
               \loop% tant que...�\idx*\loop�
                       \unless\ifeof#1\relax% ...la fin du fichier n'est pas atteinte�\tidx*{unless}\tidx*{ifeof}�
                               \xread#1 to \current@line% lire une ligne��*\xread�
                               \unless\ifx\current@line\empty% si elle n'est pas vide�\idx*\empty�
                                       % examniner les champs qu'elle contient (aller � \test@field)
                                       \expsecond{\expandafter\test@field\current@line\@nil}\macro@name%�\defline\aaa �*\expsecond�
                               \fi
               \repeat�\idx*\repeat�
       \fi
       \closein#1\relax�\idx*\closein�
}

\def\test@field#1,#2\@nil#3{% #1=champ no 1 #2=autres champs #3=nom de la macro sans "\"
       \def\current@firstfield{#1}% stocke le premier champ de la ligne en cours
       \ifx\current@firstfield\sought@firstfield% s'il est �gal � celui cherch�
               \defname{#3.\csname fieldname1\endcsname}{#1}% d�finir la macros \<#3."champ 1">��*\defname�
               \field@cnt=1 % initialiser le compteur de champ
               \doforeach\current@field\in{#2}% puis, pour i>2, d�finir les macros \<#3."champ i">��*\doforeach�
                       {\advance\field@cnt1 % incr�menter le compteur de champ
                       \letname{#3.\csname fieldname\number\field@cnt\endcsname}=\current@field��*\letname�
                       }%
               \defname{#3}##1{% et d�finir la macro \<#3>��*\defname�
                       \ifcsname#3.##1\endcsname% si la macro \<#3."argument"> existe d�j�\tidx*{ifcsname}�
                               \csname#3.##1\expandafter\endcsname% l'ex�cuter apr�s avoir mang� le \fi
                       \fi
               }%
       \fi
}
\catcode`\@12

\searchitem\rtest{fournitures.txt}{4562u}\monarticle��*\searchitem�
r�f = \monarticle{ref},
d�nomination = \monarticle{item},
prix = \monarticle{prix},
fournisseur = \monarticle{fournisseur},
champ non existant = \monarticle{foobar}.

\searchitem\rtest{fournitures.txt}{truc}\essai% r�f�rence "truc" n'existe pas��*\searchitem�
r�f = \essai{ref},
d�nomination = \essai{item},
prix = \essai{prix},
fournisseur = \essai{fournisseur}.|

La macro �\macroname, donn�e tout au d�but, doit �tre suivie d'une \verb|\<macro>| et se d�veloppe en le nom de cette \verb|\<macro>| sans l'�ventuel caract�re d'�chappement.

\begin{exercice}
Programmer une am�lioration de la macro �\searchitem pour que la recherche puisse se faire sur n'importe quel champ. Les champs seront sp�cifi�s par leur num�ro et non plus par leur nom. La syntaxe sera :

\centrecode-\searchitem<canal>{<nom fichier>}{<num�ro champ>=<valeur>}\<macro>-

La modification de la syntaxe concerne le 3\ieme{} argument et l'introduction du \verb|<num�ro champ>| que l'on souhaite chercher. Si ce \verb|<num�ro champ>| et le signe \verb|=| sont absent, le \verb|<num�ro champ>| sera pris �gal � 1.

On supposera que le fichier �\verb|basecourse.txt|� recueille les donn�es des participants � une course � pied et contient :
\immediate\openout\wtest= basecourse.txt
\exactwrite\wtest|Nom,Pr�nom,Classement,Naissance,Licenci�,Temps
Demay,Pierre,237,27/8/1986,oui,2h37
Leblanc,Nicolas,187,4/9/1978,non,2h05
Valet,Bruno,78,25/11/1989,oui,1h47
Hachel,Andr�,283,2/3/1972,non,2h42
Jalabert,Jean,165,19/1/1982,Oui,2h01|%
\immediate\closeout\wtest

\centrecode-Nom,Pr�nom,Classement,Naissance,Licenci�,Temps
Demay,Pierre,237,27/8/1986,oui,2h37
Leblanc,Nicolas,187,4/9/1978,non,2h05
Valet,Bruno,78,25/11/1989,oui,1h47
Hachel,Andr�,283,2/3/1972,non,2h42
Jalabert,Jean,165,19/1/1982,Oui,2h01-

Si l'on �crit

\centrecode-\searchitem\rtest{basecourse.txt}{3=283}\coureur-

alors, �\searchitem doit chercher la ligne o� le 3\ieme{} champ vaut 283. Par la suite, la macro \verb|\coureur| doit admettre un argument \emph{num�rique} \verb|<i>| et \verb|\coureur{<i>}| doit renvoyer la valeur du champ \no\verb|<i>|. Par exemple, \verb|\coureur{2}| doit renvoyer �Andr�.
\solution
Les modifications � apporter ne sont pas tr�s nombreuses.

Tout d'abord, il faut lire la premi�re ligne et l'ignorer : elle n'est d'aucune utilit�. Ensuite, il faut traiter correctement l'argument \verb|#3| selon qu'il contient le signe \verb|=| ou pas. � l'issue de ce traitement, on a stock� le num�ro du champ et sa valeur dans 2 macros pour les utiliser plus tard.

Dans le code pr�c�dent, la boucle \idx\loop �tait parcourue jusqu'� ce que \tidx{ifeof} soit vrai. Une petite am�lioration consiste � permettre une sortie pr�matur�e si la ligne est trouv�e. Pour cela, un bool�en cr�� avec \idx\newif sera initialis� � vrai et mis � faux s'il faut sortir de la boucle \idx\loop :

\begin{itemize}
       \item soit lorsque le test \tidx{ifeof} est vrai;
       \item soit parce que la ligne a �t� trouv�e.
\end{itemize}

\showcode/\def\macroname{% se d�veloppe en le nom de la macro qui suit sans ��*\macroname�
              % le caract�re d'�chappement
       \ifnum\escapechar>-1 % si le caract�re d'�chappement est positif�\idx*\escapechar�
               \ifnum\escapechar<256 % et inf�rieur � 256, d�velopper les 2 "\fi"
                       \expandafter\expandafter\expandafter\expandafter% et le "\string", puis
                       \expandafter\expandafter\expandafter\gobone% manger le "\" avec \gobone
               \fi
       \fi
       \string% doit �tre suivi d'une macro�\idx*\string�
}
\catcode`\@11
\newcount\field@cnt
\newif\ifsearch@repeat�\idx*\newif�
\def\assign@arg#1=#2\@nil{%
       \def\sought@fieldnumber{#1}% no du champ � chercher
       \def\sought@fielvalue{#2}% et sa valeur
}
\def\searchitem#1#2#3#4{% #1= canal  #2=nom fichier #3=champ cherch�  #4=macro � d�finir��*\searchitem�
       \let#4\gobone% pour l'instant, #4=\gobone
       \openin#1=#2\relax%�\idx*\openin�
       \unless\ifeof#1% si le fichier existe�\tidx*{unless}\tidx*{ifeof}�
               \edef\macro@name{\macroname#4}% nom de la macro sans "\"��*\macroname�
               \xread#1 to \current@line% lire et ignorer la premi�re ligne��*\xread�
               \ifin{#3}{=}% si #3 contient =��*\ifin�
                       {\assign@arg#3\@nil}% trouver le no de champ et sa valeur
                       {\def\sought@fieldnumber{1}% sinon, no du champ = 1
                       \def\sought@fielvalue{#3}% et sa valeur = #3
                       }%
               % ################ lecture des lignes de donn�es ################
               \search@repeattrue% poursuite de la boucle loop : vraie
               \loop% tant que...�\idx*\loop�
                       \ifeof#1\relax% ...la fin du fichier n'est pas atteinte�\tidx*{unless}\tidx*{ifeof}�
                               \search@repeatfalse% sortir de la boucle loop
                       \else
                               \xread#1 to \current@line% lire une ligne��*\xread�
                               \unless\ifx\current@line\empty% si elle n'est pas vide�\idx*\empty�
                                       % examniner les champs qu'elle contient (aller � \test@field)
                                       \expsecond{\expandafter\test@field\current@line\@nil}\macro@name%�\defline\aaa �*\expsecond�
                               \fi
                       \fi
                       \ifsearch@repeat% ne poursuivre que si le bool�en en vrai
               \repeat�\idx*\repeat�
       \fi
       \closein#1\relax�\idx*\closein�
}

\def\test@field#1\@nil#2{% #1=champs #2=nom de la macro sans "\"
       \field@cnt=0 % initialiser le compteur de champ
       \doforeach\current@field\in{#1}% parcourir les champs de la ligne en cours��*\doforeach�
               {\advance\field@cnt1 % incr�menter le compteur de champ
               \ifnum\field@cnt=\sought@fieldnumber\relax% si c'est le bon num�ro de champ
                       \ifx\current@field\sought@fielvalue% et si le champ correspond � celui cherch�
                               \search@repeatfalse% sortir de la boucle loop
                               \doforeachexit% sortir de la boucle \doforeach en cours��*\doforeachexit�
                       \fi
               \fi
               }%
       \unless\ifsearch@repeat% si la ligne a �t� trouv�e
               \field@cnt=0 % initialiser le compteur de champ
               \doforeach\current@field\in{#1}% parcourir � nouveau les champs de la ligne��*\doforeach�
                               {\advance\field@cnt1 % incr�menter le compteur de champ
                               \letname{#2.\number\field@cnt}=\current@field% faire l'assignation��*\letname�
                               }%
               \defname{#2}##1{% et d�finir la macro \<#2>��*\defname�
                       \ifcsname#2.##1\endcsname% si la macro \<#2."argument"> existe d�j�\tidx*{ifcsname}�
                               \csname#2.##1\expandafter\endcsname% l'ex�cuter apr�s avoir mang� le \fi
                       \fi
               }%
       \fi
}
\catcode`\@12
a) \searchitem\rtest{basecourse.txt}{3=283}\foo
  "\foo1", "\foo2", "\foo3", "\foo4", "\foo5", "\foo6", "\foo7"

b) \searchitem\rtest{basecourse.txt}{Valet}\bar
  "\bar1", "\bar2", "\bar3", "\bar4", "\bar5", "\bar6", "\bar{abcd}"/
\end{exercice}

\subsection{Afficher le contenu exact d'un fichier}
Nous allons maintenant programmer une macro �\showfilecontent[|(] de syntaxe

\centrecode-\showfilecontent<canal>{<nom du fichier>}-

\noindent qui affiche le contenu du fichier pass� en argument, en police � chasse fixe. Le but est d'imiter pour les fichiers la primitive \idx\meaning qui donne le texte de remplacement d'une macro.

Il va falloir agir sur les codes de cat�gorie avec les macros \idx\do et \idx\dospecials de plain-\TeX{} pour rendre tous les tokens inoffensifs, sauf l'espace qui sera rendu actif avec \idx\obeyspaces.

Le fichier �\verb|readtext.txt|� utilis� dans l'exemple contient 3 lignes :

\centrecode-Programmer en \TeX{} est   facile

et utile-

\immediate\openout\wtest=readtest.txt
\exactwrite\wtest|Programmer en \TeX{} est   facile

et utile|%
\immediate\closeout\wtest

\showcode|\def\showfilecontent#1#2{% #1=canal de lecture #2=nom de fichier��*\showfilecontent�
       \begingroup
               \tt% s�lectionner la fonte � chasse fixe�\idx*\tt�
               \openin#1=#2\relax�\idx*\openin�
               \ifeof#1% si la fin du fichier est d�j� atteinte, il n'existe pas et�\tidx*{ifeof}�
                       Le fichier n'existe pas% afficher le message
               \else% le fichier existe
                       \def\do##1{\catcode`##1=12 }%�\idx*\do�
                       \dospecials% neutraliser tous les tokens sp�ciaux�\idx*\dospecials�
                       \obeyspaces% rendre l'espace actif�\idx*\obeyspaces\defline\bbb�
                       \loop�\idx*\loop�
                               \xread#1 to \currline% lire une ligne��*\xread�
                               \unless\ifeof#1% si la fin du fichier n'est pas atteinte�\tidx*{unless}\tidx*{ifeof}�
                               \leavevmode\par% aller � la ligne�\idx*\leavevmode\defline\aaa�
                               \currline% afficher la ligne lue
                       \repeat% recommencer�\idx*\repeat�
               \fi
               \closein#1\relax�\idx*\closein�
       \endgroup
}

Contenu du fichier : "\showfilecontent\rtest{readtest.txt}", affich� tel quel|

Il est int�ressant de noter qu'un \idx\obeyspaces est �crit � la ligne \no\bbb{} car

\centrecode-\letactive\ =\space-�*\letactive\idx*\space{}

\noindent ne fonctionnerait pas puisque que �\letactive, tout comme �\defactive, \emph{n�cessite} que le caract�re �\verb|~|� soit actif. Or, ce n'est plus le cas ici puisque \idx\dospecials l'a rendu de catcode 12.

En revanche, placer \verb|\letactive\ =\space|�*\letactive\idx*\space{} avant le \idx\dospecials aurait fonctionn�.

\begin{exercice}
Expliquer pourquoi le guillemet initial ne se situe pas juste avant le mot �\verb|D�but|� et proposer une solution pour que cela soit le cas.
\solution
Chaque ligne affich�e, contenue dans la macro \verb|\currline|, est pr�c�d�e de \idx\leavevmode\idx\par (ligne \no\aaa), y compris pour la premi�re ligne lue. De par la structure de la macro �\showfilecontent, un \idx\par est donc toujours ins�r� entre le guillemet initial et le premier caract�re du fichier.

Une solution originale est de garder �\verb|\leavevmode\par|� sauf que l'on va mettre une macro �magique� �\magicpar en lieu et place de \idx\par. Cette macro aux vertus sp�ciales doit n'avoir aucun effet pour l'affichage la premi�re fois et ex�cuter un \idx\par les autres fois. Pour r�pondre � ces contraintes, �\magicpar doit se modifier elle-m�me en \idx\par la premi�re fois qu'elle sera ex�cut�e. Voici comment la d�finir :

\centrecode-\def\magicpar{\let\magicpar=\par}-

Avec une telle d�finition, �\magicpar ne va rien afficher la premi�re fois qu'elle sera ex�cut�e, mais va silencieusement se red�finir pour devenir �gale � \idx\par. Nous avons bien cr�� une macro locale au groupe semi-simple, qui est neutre pour l'affichage la premi�re fois et �quivalente � \idx\par ensuite.

\showcode|\def\showfilecontent#1#2{% #1=canal de lecture #2=nom de fichier��*\showfilecontent�
       \begingroup
               \tt% s�lectionner la fonte � chasse fixe�\idx*\tt�
               \openin#1=#2\relax�\idx*\openin�
               \ifeof#1% si la fin du fichier est d�j� atteinte, il n'existe pas et
                       Le fichier n'existe pas% afficher le message
               \else% le fichier existe
                       \def\do##1{\catcode`##1=12 }%�\idx*\do�
                       \dospecials% neutraliser tous les tokens sp�ciaux�\idx*\dospecials�
                       \obeyspaces% rendre l'espace actif�\idx*\obeyspaces�
                       \def\magicpar{\let\magicpar=\par}%��*\magicpar�
                       \loop�\idx*\loop�
                               \xread#1 to \currline% lire une ligne��*\xread�
                               \unless\ifeof#1% si la fin du fichier n'est pas atteinte�\tidx*{unless}\tidx*{ifeof}�
                               \leavevmode\magicpar% former le paragraphe (sauf � la 1er it�ration)�\idx*\leavevmode�
                               \currline% afficher la ligne
                       \repeat% recommencer�\idx*\repeat�
               \fi
               \closein#1\relax�\idx*\closein�
       \endgroup
}

Contenu du fichier : "\showfilecontent\rtest{readtest.txt}", affich� tel quel|
\end{exercice}�*\showfilecontent[|)]\idx*[|)]{fichier!lecture}

\section{�crire dans un fichier}\idx*[|(]{fichier!�criture}
\subsection{La primitive \texttt{\textbackslash write}}\idx*[|(]\write
Il est facile de deviner par sym�trie que si \TeX{} dispose de 16 canaux pour lire un fichier, il en dispose aussi de 16 pour �crire dans un fichier. Et le pendant de la macro \idx\newread est �videmment \idx\newwrite, qui en partage la syntaxe et qui alloue globalement un canal d'�criture libre.

\begin{regle}
\relax\TeX{} dispose de 15 canaux d'�criture portant les num�ros de 0 � 15.

On demande l'allocation d'un canal d'�criture par\idx*\newwrite

\centrecode-\newwrite\<macro>-

et ce faisant, la \verb|\<macro>| devient �quivalente � un \verb|<nombre>|, qui est un num�ro de canal libre. Un \verb|<canal>| est donc un \verb|<nombre>| explicitement �crit ou une macro d�finie avec \idx\newwrite.
\medbreak

Avant d'�crire dans un fichier, on doit d'abord lier un \verb|<canal>| � un fichier avec\idx*\openout :

\centrecode-\openout<canal>= <nom du fichier>-

\noindent et lorsque les op�rations d'�criture sont termin�es, on d�solidarise le \verb|<canal>| du fichier par \idx*\closeout

\centrecode-\closeout<canal>= <nom du fichier>-

\noindent Une ligne vide est ins�r�e en fin de fichier.

Pour �crire une ligne dans le fichier, on �crit :

\centrecode-\write<canal>{<texte>}-

\noindent o� le \verb|<texte>| est un code dans lequel les accolades sont �quilibr�es. L'�criture dans le fichier n'a pas lieu lorsque la commande \idx\write est rencontr�e, mais lorsque la page courante est compos�e. Le \verb|<texte>| est stock� dans la m�moire de \TeX{} et est d�velopp� au maximum lorsque \TeX{} �crit dans le fichier. Si l'utilisateur souhaite bloquer le d�veloppement, il lui appartient de le bloquer � l'aide des m�thodes vues � la page~\pageref{bloquer.developpement.maximum}.
\grandsaut

Les op�rations li�es � l'�criture dans un fichier (\idx\openout, \idx\write et \idx\closeout) ont la particularit� d'avoir lieu lorsque la page est compos�e, c'est-�-dire plus tard dans le temps que lorsque les instructions sont rencontr�es. Ce d�calage temporel est bien utile lorsqu'on souhaite �crire un \idx{num�ro de page} puisque l'on s'assure que le bon num�ro de page sera �crit, mais il est ind�sirable pour �crire des donn�es non sensibles au positionnement dans le document. Pour s'affranchir de cette d�synchronisation temporelle, il faut faire pr�c�der \idx\openout, \idx\write et \idx\closeout de la primitive � \idx\immediate � qui force les op�rations d'�criture � �tre faites imm�diatement lorsqu'elles sont rencontr�es.
\end{regle}

Dans tout le reste du chapitre, nous utiliserons le canal d'�criture \verb|\wtest| que nous allons allouer avec \idx\newwrite\verb|\wtest|.

Voici deux tentatives successives d'�criture dans un m�me fichier :

\showcode|�\string\newwrite\string\wtest�% sera le canal d'�criture dans tout ce chapitre�\idx*\newwrite�
\immediate\openout\wtest=writetest.txt % lie \wtest au fichier�\idx*\immediate\idx*\openout�
\immediate\write\wtest{Programmer en \noexpand\TeX{} est   facile.}% �crit une ligne�\idx*\write\idx*\noexpand�
\immediate\write\wtest{Et utile...}% puis une autre
\immediate\closeout\wtest% d�fait la liaison�\idx*\closeout�
a) Contenu du fichier :\par
"\showfilecontent\rtest{writetest.txt}"% affiche le contenu du fichier��*\showfilecontent�
\medbreak�\idx*\medbreak�
% 2e tentative :�\defline\aaa�
b) Contenu du fichier :\par
\immediate\openout\wtest=writetest.txt % lie \wtest au fichier
\immediate\write\wtest{Essai d'�criture}% �crit une ligne�\idx*\write�
\immediate\closeout\wtest% d�fait la liaison�\idx*\immediate�
"\showfilecontent\rtest{writetest.txt}"% affiche le contenu du fichier��*\showfilecontent�|

Remarquons � partir de la ligne \no\aaa, que si on lie un canal � un fichier d�j� existant et que l'on �crit � nouveau dans ce fichier, le contenu pr�c�dent est effac�, c'est-�-dire que l'�criture recommence au d�but du fichier.

Remarquons �galement que l'argument de \idx\write est lu par \TeX{} avant d'�tre d�tok�niz� et �crit dans le fichier. La perte d'informations lorsque \TeX{} lit du code source a donc lieu. Ici en particulier, les espaces cons�cutifs dans �\verb*|est   facile|� ont �t� lus comme un seul espace et �crits comme tel dans le fichier.

Enfin, il faut noter que \idx\write, lorsqu'il d�tok�nize le \verb|<texte>|, rajoute un espace apr�s les s�quences de contr�le.

\subsection{Programmer des variantes de \texttt{\textbackslash write}}
\subsubsection{La macro \texttt{\char`\\noexpwrite}}�*\noexpwrite
Si la primitive \idx\write d�veloppe au maximum ce qu'elle va �crire, il est logique de construire un �quivalent qui lui, ne proc�dera � aucun d�veloppement. Parmi des m�thodes � notre disposition pour bloquer le d�veloppement, la plus pratique est de recourir � \idx\unexpanded :

\showcode/\def\noexpwrite#1#2{% #1=num�ro de canal  #2=texte � �crire��*\noexpwrite�
       \write#1{\unexpanded{#2}}%�\idx*\write\idx*\unexpanded�
}
\immediate\openout\wtest=writetest.txt �\idx*\openout�
\immediate\noexpwrite\wtest{Programmer en \TeX{} est   facile.}%�\idx*\immediate�
\immediate\noexpwrite\wtest{Et utile...}%��*\noexpwrite�
\immediate\closeout\wtest�\idx*\closeout�
Contenu du fichier :\par
\showfilecontent\rtest{writetest.txt}% affiche le contenu du fichier��*\showfilecontent�/

Ici encore, comme l'argument \verb|#2| a �t� lu par la macro �\noexpwrite, les m�mes pertes d'information que pr�c�demment ont eu lieu. Le seul moyen d'�crire dans le fichier ce qu'il y a \emph{exactement} dans le code source est de proc�der comme avec la macro �\litterate (voir page~\pageref{litterate}).

\subsubsection{La macro \texttt{\char`\\exactwrite}}\label{exactwrite}�*\exactwrite[|(]
Nous allons cr�er l'�quivalent de la macro �\litterate pour l'�criture dans un fichier, c'est-�-dire une macro qui �crit dans un fichier \emph{tous} les caract�res qu'on lui donne � lire. Appelons cette macro �\exactwrite et par commodit�, sa syntaxe va ressembler � celle de �\litterate. La primitive \idx\immediate sera appel�e et donc l'�criture sera synchrone. On suppose qu'un \verb|<canal>| a d�j� �t� li� au fichier dans lequel on veut �crire. La syntaxe sera :

\centrecode-\exactwrite{<canal><car><texte><car>-

\noindent Ici, \verb|<car>| sera un caract�re choisi par l'utilisateur qui servira de d�limiteur au \verb|<texte>| que l'on veut �crire dans le fichier, avec la limitation classique que \verb|<car>| doit �tre choisi de telle sorte qu'il ne figure pas dans le \verb|<texte>|.

On va proc�der comme avec �\litterate en rendant inoffensifs des tokens en mettant leurs catcodes � 12, sauf qu'ici, cela va concerner \emph{tous} les octets, de 0 � 255. C'est certes un rem�de de cheval, mais de cette fa�on, tous les caract�res peuvent �tre �crits sur un fichier et ce quels que soient l'\idx{encodage} du fichier source et le r�gime de catcode en cours.

La m�thode va �tre la suivante :

\begin{algo}
       \item lire le \verb|<canal>|;
       \item ouvrir un groupe, mettre le catcode de tous les octets � 12;
       \item lire le \verb|<car>| (qui sera de catcode 12 � cause du point pr�c�dent) ;
       \item isoler le \verb|<texte>| qui se trouve jusqu'au prochain \verb|<car>|;
       \item si ce \verb|<texte>| contient le retour charriot �\verb|^^M|\verbidx*[ (retour charriot)]{^^M}� (de catcode 12) :
       \begin{algo}
               \item �crire dans le fichier le texte se trouvant avant \verb|^^M|;
               \item retourner en 5) avec en prenant \verb|<texte>| �gal � ce qu'il y a pr�s \verb|^^M|;
       \end{algo}
       \item sinon �crire le \verb|<texte>| dans le fichier et fermer le groupe.
\end{algo}

Pour forcer les catcodes de tous les octets � 12, une simple boucle �\for suffit :

\centrecode-\for\xx=0 to 255 \do{\catcode\xx=12 }-

\noindent Ensuite, comme � partir du point \no3, tout ce qui est lu est constitu� de caract�res de catcode 12, il va falloir d�finir un retour charriot de catcode 12\idx*{catcode!12 (autre)} qui nous servira de d�limiteur d'argument. On peut s'y prendre ainsi :

\centrecode-{\catcode`\^^M=12 \gdef\EOL@char{^^M}}-\idx*\gdef

Dans les grandes lignes, la t�ches vont se r�partir de la fa�on suivante. Les points \nos1 et 2 sont d�volus � la macro chapeau �\exactwrite. Une macro auxiliaire \verb|\exactwrite@i| va lire le \verb|<car>|, forc�ment de catcode 12, qui sera son unique argument. Une fois qu'elle s'est empar� de ce \verb|<car>|, elle peut d�finir une sous-macro \verb|\exactwrite@ii| dont l'argument d�limit� par ce \verb|<car>| sera le \verb|<texte>| qu'elle transmettra � la macro r�cursive \verb|\exactwrite@iii| qui se chargera des points \no5 � 6.

\showcode/\catcode`\@11
\def\exactwrite#1{% #1=num�ro de canal��*\showfilecontent�
       \begingroup
               \def\canal@write{#1}% sauvegarde le num�ro de canal
               \for\xx=0 to 255\do{\catcode\xx=12 }% donne � tous les octets le catcode 12��*\for\idx*{catcode!12\space(autre)}�
               \exactwrite@i% aller lire le <car>
}

\def\exactwrite@i#1{% #1 est le <car> de catcode 12
       \def\exactwrite@ii##1#1{% ##1 est le <texte> � envoyer vers le fichier
               \exactwrite@iii##1\@nil% envoyer <texte> � \exactwrite@iii
       }%
       \exactwrite@ii% va lire tout ce qui se trouve jusqu'au prochain <car>
}

{\catcode`\^^M 12 \gdef\EOL@char{^^M}}% d�finit le caract�re <EOL> de catcode 12�\verbidx*[ (retour charriot)]{^^M}\idx*\gdef�

\def\exactwrite@iii#1\@nil{% #1 = <texte> � �crire dans le fichier
       \expsecond{\ifin{#1}}\EOL@char% si #1 contient "retour charriot"��*\expsecond�*\ifin�
               {\write@line#1\@nil% �crire la premi�re ligne de #1
               }
               {\immediate\write\canal@write{#1}% sinon : derni�re ligne atteinte, l'�crire�\idx*\immediate\idx*\write�
               \endgroup% puis sortir du groupe
               }%
}

% les \expandafter provoquent le 1-d�veloppement de \EOL@char :
\expandafter\def\expandafter\write@line\expandafter#\expandafter1\EOL@char#2\@nil{%
       \immediate\write\canal@write{#1}% �crit la ligne (ce qui se trouve avant ^^M)�\idx*\immediate\idx*\write�
       \exactwrite@iii#2\@nil% recommencer avec ce qui se trouve apr�s "^^M"
}
\catcode`\@12

\immediate\openout\wtest=writetest.txt % lie le canal \wtest au fichier�\idx*\immediate\idx*\openout�
\exactwrite\wtest|Programmer en \TeX{} est   facile !

Et tr�s utile.|
\immediate\closeout\wtest% et fermer le fichier

Le contenu du fichier "writetest.txt" est :\par
"\showfilecontent\rtest{writetest.txt}"��*\showfilecontent�/\idx*[|)]\write

Plus pr�cis�ment, voici comment un �diteur de fichiers\footnote{Programme dont la principale fonctionnalit� est de lire les octets d'un fichier un par un, de les afficher ainsi que les caract�res ASCII correspondants s'ils sont affichables.} voit le fichier g�n�r� :

\begin{centrage}
       \ttfamily\footnotesize
       \setbox0\hbox{0}
       \edef~{\hbox to\the\wd0{\hss\noexpand\small\noexpand\textbullet\hss}}
       \catcode`\:12 \catcode`\!12
       \obeyspaces
       \catcode`\/0
       \catcode`\{12 \catcode`\}12
       \catcode`\[1 \catcode`\]2
       \catcode`\\12
       /tabular[r|l|l]%
               0000&50 72 6F 67  72 61 6D 6D  65 72 20 65  6E 20 5C 54&Programmer en \T/\%
               0010&65 58 7B 7D  20 65 73 74  20 20 20 66  61 63 69 6C&eX{} est   facil/\%
               0020&65 20 21 0A  0A 45 74 20  74 72 E8 73  20 75 74 69&e !~~Et tr�s uti/\%
               0030&6C 65 2E 0A                                       &le.~%
       /endtabular%
/end[centrage]%

L'affichage se divise en trois parties, � gauche l'�offset� (en hexad�cimal), c'est-�-dire le num�ro d'ordre du premier \idx{octet} de la ligne (le premier octet du fichier portant le num�ro 0), au centre les octets contenus dans le fichier en notation hexad�cimale et � droite les caract�res correspondant aux octets (dans un codage sur un octet, le plus souvent \latin). Les caract�res non affichables sont repr�sent�s par � {\small\textbullet} �. Constatons en premier lieu que le caract�re �� est cod� sur \emph{un seul} \idx{octet} (qui est \Hex{E8}) puisque l'\idx{encodage} utilis� dans le code source de ce livre est \latin\footnote{Si l'encodage avait �t� \utf, le caract�re �� aurait �t� cod� sur deux octets : \Hex{C3} \Hex{A8}}. Remarquons aussi que les seuls caract�res non affichables portent le code de caract�re \Hex{0A} qui est 13 en d�cimal; ce sont donc les retours charriot. Il est normal d'avoir un retour charriot en fin de fichier, car comme nous l'avons vu, \TeX{} ins�re une ligne vide en fin de fichier.�*\exactwrite[|)]

\subsection{Utilisation pratique}
Mettons � profit ce que nous savons pour �crire une macro �\exo[|(], utile pour r�diger des exercices et afficher leur bar�me. Supposons que �\verb|\exo{3.5pt}|� soit ex�cut�e. Elle devra afficher le texte suivant :

\medbreak
\noindent\vrule height1ex width1ex depth0pt\kern1ex\textbf{Exercice 3}\leaders\hbox to5pt{\hss.\hss}\hfill3.5pt/15
\medbreak

\noindent o� �15� est le total des points de toutes les macros �\exo du document.

Remarquons que la macro \verb|\exo| a �t� appel�e 2 fois auparavant puisque cet appel g�n�re le texte de l'exercice \no3.

La principale difficult� est que le total n'est pas connu lorsque la macro \verb|\exo| est ex�cut�e puisque d'�ventuels autres appels de cette macro qui sont � venir dans le code. C'est donc un cas o� il va falloir se servir d'un fichier auxiliaire pour transmettre ce total entre deux compilations avec la contrepartie que lors d'une compilation :
\begin{itemize}
       \item le fichier n'existe pas, ce qui signifierait qu'il s'agit de la premi�re compilation du document ou que le fichier auxiliaire a �t� effac�. Dans ce cas, il faudra afficher un total qui repr�sente cette situation particuli�re, par exemple �\#\#�;
       \item le total est faux parce que depuis la derni�re compilation, l'auteur du document a modifi� le bar�me d'un ou plusieurs exercices ou a chang� le nombre d'exercices.
\end{itemize}

\noindent Dans ces cas, il faudra lancer \emph{deux} compilations successives pour obtenir le total correct.
\grandsaut

Avant tout, appelons \verb|\total@points| la macro dont le texte de remplacement sera soit �\verb|##|�, soit le total des points. Il reste � prendre une d�cision; comment pouvons-nous stocker dans un fichier le total des points au fur et � mesure que le document est compil� ? Nous pouvons proc�der en 3 temps :

\begin{enumerate}
       \item au d�but du document, appeler une macro \verb|\initexo| qui va tester si le fichier auxiliaire existe.
       \begin{itemize}
               \item dans l'affirmative, elle va ex�cuter le code qu'il contient avec \idx\input. Ce code d�finira la macro \verb|\total@points| avec le bar�me de la pr�c�dente compilation;
               \item sinon, elle va placer dans le texte de remplacement de \verb|\total@points| le code �\verb|\char`\#\char`\#|� qui affiche �\char`\#\char`\#�.
       \end{itemize}

       \item elle va ouvrir ce fichier en �criture y ins�rer les caract�res �\verb|\exocalctotal|�. Puis � chaque fois que la macro \verb|\exo{<bar�me>}| est rencontr�e, ajouter les caract�res �\verb|+<bar�me>|� au fichier;
       \item � la fin du document, la macro \verb|\stopexo| �crira �\verb|\relax\endtotal|� dans le fichier et le fermera.
\end{enumerate}

Admettons par exemple que �\verb|\exo{5pt}|�, �\verb|\exo{3.5pt}|� et �\verb|\exo{3pt}|� sont rencontr�es dans le document. Alors, � la fin de la compilation (et au d�but de la suivante), le fichier auxiliaire contiendra :

\centrecode-\exocalctotal+5pt+3.5pt+3pt\relax\endtotal-

Il nous reste � dire un mot sur la macro \verb|\exocalctotal|. Elle sera d�finie pour que son argument soit d�limit� par \verb|\endtotal| et son texte de remplacement placera dans la macro \verb|\total@points| la somme de tous les points. Pour ce faire, \idx\dimexpr et �\dimtodec seront employ�es, avec les �ventuels inconv�nients concernant les erreurs d'arrondis qui peuvent survenir (voir page~\pageref{arrondis.sur.dimensions}) :

\centrecode-\def\exocalctotal#1\endtotal{\edef\total@points{\dimtodec\dimexpr#1}}-

Le fichier contenant les points sera nomm� comme le fichier maitre (nom qui est le d�veloppement de \idx\jobname), mais avec l'extension �\verb|.pts|�

\catcode`\W12
\showcode W\catcode`\@11
\newcount\exo@number% compteur pour le num�ro d'exercice�\idx*\newcount�

\def\exocalctotal#1\endtotal{\edef\total@points{\dimtodec\dimexpr#1}}��*\dimtodec�

\def\initexo#1{%
       \def\exo@canal{#1}% sauvegarde le canal d'�criture
       \exo@number=0 % initialiser le compteur d'exo
       \iffileexists\exo@canal{\jobname.pts}% si le fichier .pts existe��*\iffileexists\idx*\jobname�
               {\input \jobname.pts }% le lire et ex�cuter son contenu�\idx*\input\idx*\jobname�
               {\def\total@points{\char`\#\char`\#}}% sinon, d�finir un total alternatif�\idx*\char�
       \immediate\openout\exo@canal=\jobname.pts % ouvrir le fichier .pts�\idx*\immediate\idx*\jobname\idx*\openout�
       \immediate\write\exo@canal{\noexpand\exocalctotal}% et commencer � y �crire dedans�\idx*\noexpand\idx*\write�
}

\def\exo#1{% d�finti la macro qui affiche l'exercice
       \bigbreak% sauter une grande espace verticale
       \immediate\write\exo@canal{+#1}% �crire "+#1" dans le fichier .pts�\idx*\immediate\idx*\write�
       \advance\exo@number by 1 % incr�menter le num�ro de l'exercice�\idx*\advance�
       \noindent\vrule height1ex width1ex depth0pt % trace le carr�\idx*\noindent\idx*\vrule�
       \kern1ex% ins�rer une espace horizontale�\idx*\kern�
       {\bf Exercice \number\exo@number}% afficher "Exercice <nombre>"�\idx*\bf\idx*\number�
       \leaders\hbox to.5em{\hss.\hss}\hfill% afficher les pointill�s�\idx*\leaders\idx*\hbox\idx*\hss�
       #1/\total@points%  puis #1/<total>
       \smallbreak% composer la ligne pr�c�dente et sauter une espace verticale�\idx*\smallbreak�
}

\def\stopexo{%
       \immediate\write\exo@canal{\relax\noexpand\endtotal}%�\idx*\immediate\idx*\write\idx*\noexpand�
       \immediate\closeout\exo@canal�\idx*\closeout�
}
\catcode`\@12
\initexo\wtest

\hfill{\bf Interrogation �crite. Sujet : \TeX{}}\hfill\null�\idx*\hfill\idx*\null�
\par
\leavevmode\hfill\vrule height.4pt width 2cm depth0pt\hfill\null�\idx*\leavevmode\idx*\vrule�
\exo{3pt}
�laborer un test \litterate/\ifonebyte{<texte>}{<vrai>}{<faux>}/ qui teste, pour une��*\litterate�
compilation avec un moteur 8 bits, si le \litterate/<texte>/ est cod� sur un seul
octet. Ce test pourrait �tre utilis� pour d�terminer si l'encodage d'un document
est � plusieurs octets (comme l'est UTF8) en prenant comme \litterate/<texte>/
les caract�res <<~�~>>, <<~�~>>, etc.

\exo{5,5pt}
Si \verb-#1- est un nombre entier, quel est le test fait par ce code ?
\smallbreak�\idx*\smallbreak�
\hfill
\litterate/\if\string l\expandafter\firstto@nil\romannumeral#1\relax\@nil/
\hfill\null�\idx*[|etc]\string\forbidindex\string\idx*\romannumeral\idx*\hfill\idx*\null�*\firstto@nil�*\litterate�

\exo{4,5pt}
On a vu que pour provoquer un $n$-d�veloppement, les \litterate/\expandafter/se pla�aient
en nombre �gal � $2^n-1$ devant chaque token pr�c�dant celui que l'on veut d�velopper.
Or, ce nombre est {\it impair\/}. Trouver un exemple ou un cas particulier o� il faut�\idx*\it\idx*\/�
placer un nombre {\it pair\/} d'\litterate/\expandafter/ devant un token (on pourra �\idx*\it\idx*\/�
envisager le cas de 2 \litterate/\expandafter/).��*\litterate�
\stopexo W
\catcode`\W11

La macro �\dimtodec est ici utilis�e puisque le nombre de points n'est pas forc�ment entier. D'ailleurs, le c�t� pratique des � points � est que l'argument de \verb|\exo| est consid�r� comme un bar�me par l'utilisateur, mais il est vu comme une vraie dimension par \idx\dimexpr !

La man\oe uvre effectu�e avec \verb|\exo| est finalement tr�s courante. �crire dans un fichier lors d'une compilation pour lire des �l�ments dans ce fichier � la compilation suivante est utilis� dans beaucoup de contextes\footnote{Le format \LaTeX{} �crit des informations de localisation de sectionnement et de r�f�rences crois�es dans le fichier �\texttt{.aux}� via le canal \texttt{\string\@auxout}.}. Pour afficher une table des mati�res en d�but de document, il faudrait, � l'aide d'une macro sp�ciale de sectionnement, d'abord stocker dans un fichier les titres assortis de leurs num�ros de page, sachant que le \idx{num�ro de page} courant est contenu dans le compteur \idx\count\verb|0| pour plain-\TeX{} et \LaTeX{}\catcode`\@11 \footnote{Le nom qui lui est donn� diff�re selon le format : plain-\TeX{} demande �\idx\countdef{}\idx\pageno{}\texttt{=0} � tandis que \LaTeX{} pr�f�re �\idx\countdef{}\idx\c@page{}\texttt{=0} �.}\catcode`\@12. D�s lors, � la compilation suivante et sous r�serve qu'aucune modification du fichier source n'ait �t� effectu�e entre temps, les instructions �crites dans le fichier refl�tent les bons num�ros de page.

La construction d'un index repose sur le m�me stratag�me.�*\exo[|)]
\grandsaut

Pour les lecteurs consciencieux, voici les r�ponses aux exercices donn�s dans cet exemple :

\begingroup
\small
\parindent0pt
\solution[exercice 1]
La solution apparait imm�diatement en utilisant la macro �\ifempty et \verb|\gobone|, qui va enlever un \idx{octet} � \verb|#1| et que nous prenons soin de d�velopper avant de tester :

\centrecode|\def\ifonebyte#1{\expandafter\ifempty\expandafter{\gobone#1}}|

\solution[exercice 2]
Le test est positif si la lettre �\verb|l|� est la lettre de gauche du nombre �crit en chiffres romains. Ce cas ne se pr�sente que si l'entier est compris entre 50 et 89 (qui s'�crivent �\texttt{\romannumeral50} � et �\texttt{\romannumeral89} �). Ce test est donc positif pour les entiers allant de 50 � 89 compris et n�gatif pour tous les autres.

\solution[exercice 3]
Le code \verb|\expandafter\expandafter<token>| proc�de au 1-d�veloppement de \verb|<token>| puis au 1-d�veloppement du deuxi�me token du code qui r�sulte de ce d�veloppement.

Voici un cas o� 2 \idx\expandafter se justifient :

\showcode/\def\identite{Foo Bar}% Pr�nom Nom
\def\beforespace#1 #2\nil{#1}
\def\afterspace#1 #2\nil{#2}
\def\prenom{\beforespace\identite\nil}
\def\nom{\afterspace\identite\nil}
Mon pr�nom : \expandafter\expandafter\prenom�\defline\aaa�

Mon nom : \expandafter\expandafter\nom/

� la ligne \no\aaa, l'\idx\expandafter de gauche effectue ce d�veloppement :
\medbreak
\hfill\verb|\prenom|\quad$\longrightarrow$\quad\verb|\beforespace\identite\nil|\hfill\null
\medbreak
\noindent et celui de droite 1-d�veloppe \verb|\itentite| en �\verb|Foo Bar|� de telle sorte que le code finalement obtenu est :

\centrecode-\beforespace Foo Bar\nil-
\endgroup\idx*[|)]{fichier!�criture}

\section{\texttt{\textbackslash newlinechar} et \texttt{\textbackslash endlinechar}}
L'entier \idx\newlinechar repr�sente le code du caract�re qui ordonne � \TeX{} de commencer une nouvelle ligne lors d'une op�ration avec \idx\write. D�s lors, il devient possible d'�crire en une op�ration plusieurs lignes dans un fichier. Plain-\TeX{} assigne $-1$ � cet entier ce qui signifie qu'aucun caract�re ne rev�t cette propri�t�. \LaTeX, en revanche, y range l'entier \number`\^^J{} qui est le code de caract�re de \verb|LF| (le caract�re \verbidx*[ (fin de ligne)]{^^J}\verb|^^J|).

\showcode|\newlinechar`\^^J �\idx*\newlinechar\verbidx*[ (fin de ligne)]{^^J}�
\immediate\openout\wtest=test1.txt �\idx*\immediate\idx*\openout�
\immediate\write\wtest{Une premi�re ligne^^JEt une seconde.}�\idx*\write�
\immediate\closeout\wtest �\idx*\closeout�
\showfilecontent\rtest{test1.txt}��*\showfilecontent�|

\Qu ant � l'entier \idx\endlinechar, il s'applique �galement lors des op�rations de lecture, c'est-�-dire que le caract�re dont le code est \idx\endlinechar sera ins�r� � la fin de chaque ligne lue, qu'elle se trouve dans le fichier � lire ou dans le code source. Si ce caract�re est modifi� localement afin d'obtenir des effets sp�ciaux lors de la lecture d'un fichier, il faut penser � commenter les fins de ligne de la partie du code source concern�e pour que ces effets ne s'y appliquent pas aussi.

\showcode|\newlinechar`\^^J �\idx*\newlinechar\verbidx*[ (fin de ligne)]{^^J}�
\immediate\openout\wtest=test2.txt �\idx*\immediate\idx*\openout�
\immediate\write\wtest{Une premi�re ligne^^JEt une seconde.}�\idx*\write�
\immediate\write\wtest{Et la derni�re.}�\idx*\write�
\immediate\closeout\wtest �\idx*\closeout�

{\endlinechar`\X % ins�re "X" � chaque fin de ligne�\idx*\endlinechar�
\openin\rtest=test2.txt % les fins de lignes sont comment�es�\idx*\openin�
\loop%                    pour �viter que \endlinechar �\idx*\loop�
       \read\rtest to \foo%    ne soit ins�r� � chaque fin de�\idx*\read�
       \unless\ifeof\rtest%    ligne du code source�\tidx*{unless}\tidx*{ifeof}�
       \meaning\foo\par%       affiche le texte de remplacement de \foo�\idx*\meaning�
\repeat%�\idx*\repeat�
\closein\rtest}%|

\begin{exercice}
Utiliser \idx\newlinechar pour simplifier la macro �\exactwrite vue � la page~\pageref{exactwrite}.
\solution
Rappelons-nous que le \verb|<texte>|, susceptible de contenir des retours � la ligne, �tait lu de telle sorte que tous les octets aient un catcode de 12. Au lieu d'�crire une macro r�cursive qui lit une seule ligne � chaque it�ration pour l'�crire dans le fichier, il est bien plus �l�gant et rapide d'assigner � \idx\newlinechar l'entier \verb|`\^^M|\verbidx*[ (retour charriot)]{^^M}. Une fois ceci fait, il ne reste plus qu'� �crire en une seule fois le \verb|<texte>| dans le fichier :

\showcode/\catcode`\@11
\def\exactwrite#1{% #1=num�ro de canal��*\exactwrite�
       \begingroup
               \for\xx=0 to 255\do{\catcode\xx=12 }% donne � tous les octets le catcode 12��*\for\idx*{catcode!12\space(autre)}�
               \newlinechar=`\^^M % caract�re de fin de ligne = retour charriot�\idx\newlinechar\idx*{caract�re de fin de ligne}�
               \exactwrite@i{#1}% donne le <canal> d'�criture comme premier argument
}

\def\exactwrite@i#1#2{% #2 est le caract�re d�limiteur de catcode 12
       \def\exactwrite@ii##1#2{% ##1 est le <texte> � envoyer vers le fichier
               \immediate\write#1{##1}% �crire le <texte> dans le fichier
               \endgroup% puis, sortir du groupe
       }%
       \exactwrite@ii% traiter tout ce qui se trouve jusqu'au prochain #2
}
\catcode`\@12

\immediate\openout\wtest=writetest.txt % lie le canal \wtest au fichier�\idx*\openout�
\exactwrite\wtest|Programmer en \TeX{} est   facile !��*\exactwrite�

Et tr�s utile.|
\immediate\closeout\wtest% et fermer le fichier

Le contenu du fichier "writetest.txt" est :\par
"\showfilecontent\rtest{writetest.txt}"��*\showfilecontent�/
\end{exercice}

\section{Autres canaux d'entr�e-sortie}
En plus des 16 canaux de lectures ou d'�criture, \TeX{} dispose de canaux sp�ciaux. En ce qui concerne la lecture, si le \verb|<canal>| qui suit \idx\read n'est pas compris entre 0 et 15 ou si aucun fichier n'a pu �tre ouvert (notamment parce que le fichier n'existe pas) ou encore si la fin du fichier a �t� atteinte (et donc le test \tidx{ifeof} est devenu vrai) alors, la lecture de la ligne courante se fait � partir du terminal : \TeX{} attend que l'utilisateur tape un texte au clavier et finisse par la touche � entr�e � (\bioLegacyKeyGlyph{E_n_t_e_r})\footnote{Ce moyen de collecter interactivement des informations n'est possible que lorsque l'ex�cutable pfd\TeX{} est appel� \emph{sans} l'option �\texttt{-interaction=nonstopmode}� qui l'interdit !}. Un message d'invite est affich� sur le terminal sauf lorsque le \verb|<canal>| est strictement n�gatif. Si on �crit

\centrecode|\read16 to \foo|

\noindent alors, l'invite est �\verb|\foo=|�

\grandsaut
Du c�t� de l'�criture, la primitive \idx\message\verb|{<texte>}| a pour action d'�crire le \verb|<texte>| sur le terminal et dans le \idx[!log]{fichier} \verb|log| apr�s avoir d�velopp� au maximum ce \verb|<texte>|. Il convient de s'assurer que ce \verb|<texte>| est purement d�veloppable et dans le cas contraire, bloquer le d�veloppement de certaines de ces parties avec \idx\noexpand ou \idx\unexpanded.

Si on utilise \idx\write\verb|<canal>|, si le \verb|<canal>| n'est pas compris entre 0 et 15 ou si le flux sp�cifi� par le \verb|<canal>| n'a pas �t� li� � un fichier par \idx\openout, l'�criture est dirig�e vers le \idx[!log]{fichier} \verb|log| et vers le terminal, et uniquement vers le \idx[!log]{fichier} \verb|log| si le \verb|<canal>| est strictement n�gatif.

Il est donc assez facile de converser avec l'utilisateur :

\errcode|\newlinechar`\^^J �\idx*\newlinechar\verbidx*[ (fin de ligne)]{^^J}�
\message{^^JQuel est votre nom ? }�\idx*\message�
\xread-1 to \username��*\xread�
\message{Bonjour \username.^^J%
Depuis combien d'ann�es pratiquez-vous TeX ? }
\read-1 to \yeartex �\idx*\read�
\message{%�\idx*\message�
       \ifnum\yeartex<5 Cher \username, vous �tes encore un d�butant !
       \else\ifnum\yeartex<10 Bravo \username, vous �tes un TeXpert !
       \else\ifnum\yeartex<15 F�licitations \username, vous �tes un TeXgourou.
       \else Passez � autre chose, par exemple � Metafont et Metapost !
       \fi\fi\fi^^J}|{Quel est votre nom ? Christian\par
Bonjour Christian.\par
Depuis combien d'ann�es pratiquez-vous TeX ? 8\par
Bravo Christian, vous �tes un TeXpert !}
\grandsaut

Voici pour finir comment \TeX{} pourrait, par dialogue avec l'utilisateur et en proc�dant par dichotomie, trouver un nombre entre 1 et 100 choisi au hasard par l'utilisateur :

\errcode|\catcode`\@11
\def\answer@plus{+}\def\answer@minus{-}\def\answer@equal{=}%
\def\nb@found#1{% macro appel�e lorsque le nombre (argument #1) est trouv�
       \message{^^JVotre nombre est #1.^^JMerci d'avoir jou� avec moi.^^J}%�\idx*\message�
}

\def\nbguess#1#2{%
       \message{Choisissez un nombre entre #1 et #2.^^J�\idx*\message�
       Tapez entr�e lorsque c'est fait.}%
       \read-1 to \tex@guess% attend que l'on tape sur "entr�e"�\idx*\read�
       \nbguess@i{#1}{#2}%
}

\def\nbguess@i#1#2{%
       \ifnum#1<#2  \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               % si #1<#2 (donc le nombre n'est pas trouv�),
               % mettre dans \tex@guess la troncature de la moyenne de #1 et #2
               {\edef\tex@guess{\number\truncdiv{\numexpr#1+#2\relax}2}%��*\truncdiv�
               \message{Je propose \tex@guess.^^J% afficher sur le terminal�\idx*\message�
               Votre nombre est-il plus grand (+), plus petit (-) ou �gal (=) : }%
               \read -1 to \user@answer% lire la r�ponse de l'utilisateur�\idx*\read�
               \edef\user@answer{%
                       \expandafter\firstto@nil\user@answer\relax\@nil% ne garder que le 1er caract�re��*\firstto@nil�
               }%
               \ifxcase\user@answer% envisager les cas "+", "-" et "="��*\ifxcase�
                       \answer@plus{\exparg\nbguess@i{\number\numexpr\tex@guess+1\relax}{#2}}%��*\exparg�
                       \answer@minus{\expsecond{\nbguess@i{#1}}{\number\numexpr\tex@guess-1\relax}}%��*\expsecond�
                       \answer@equal{\nb@found\tex@guess}%
               \elseif% si la r�ponse ne commence pas par "+", "-" ou "="��*\elseif�
                       \message{Je n'ai pas compris votre r�ponse}% afficher message erreur�\idx*\message�
                       \nbguess@i{#1}{#2}% et recommencer avec les m�mes nombres
               \endif��*\endif�
               }
               % si #1>=#2, le nombre est trouv�
               {\nb@found{#1}}%
}
\catcode`\@12

\nbguess{1}{100}|{Choisissez un nombre entre 1 et 100.\par
Tapez entr�e lorsque c'est fait.\par
\leavevmode\par
Je propose 50.\par
Votre nombre est plus grand (+), plus petit (-) ou �gal (=) : -\par
\leavevmode\par
Je propose 25.\par
Votre nombre est plus grand (+), plus petit (-) ou �gal (=) : +\par
\leavevmode\par
Je propose 37.\par
Votre nombre est plus grand (+), plus petit (-) ou �gal (=) : -\par
\leavevmode\par
Je propose 31.\par
Votre nombre est plus grand (+), plus petit (-) ou �gal (=) : -\par
\leavevmode\par
Je propose 28.\par
Votre nombre est plus grand (+), plus petit (-) ou �gal (=) : +\par
\leavevmode\par
Je propose 29.\par
Votre nombre est plus grand (+), plus petit (-) ou �gal (=) : +\par
\leavevmode\par
Votre nombre est 30.\par
Merci d'avoir jou� avec moi.}\idx*[|)]{fichier}

\chapter{Autres algorithmes}
Dans ce chapitre qui sera d�pourvu d'exercice, nous allons nous attacher � �crire quelques algorithmes --~des classiques de la programmation~-- en \TeX{}.

\section{Macros de calcul}
\subsection{La suite de Syracuse}
Pour g�n�rer une suite de \idx[ (suite de)|(]{Syracuse}, le proc�d� consiste � choisir un nombre entier strictement positif. S'il est pair, on le divise par 2 ; s'il est impair, on le multiplie par 3 et on ajoute 1. En r�p�tant l'op�ration, on g�n�re une suite d'entiers appel�e � suite de Syracuse �. Si � partir d'un certain rang, l'entier 1 est atteint, la suite de valeurs 1; 4; 2 se r�p�te infiniment et ces trois valeurs constituent ce que l'on appelle le � cycle trivial �. La conjecture de Syracuse, non d�montr�e, affirme que, quel que soit l'entier choisi au d�part, on arrive au bout d'un nombre fini d'it�rations � la valeur 1 et donc au cycle trivial.

Nous allons programmer une macro �\syracuse\verb|{<nombre>}|, purement d�veloppable qui va afficher toutes les valeurs g�n�r�es selon le proc�d� d�crit ci-dessus, et s'arr�ter lorsque la valeur 1 est atteinte.

Nous aurons recours au test

\centrecode-\ifodd<nombre><code vrai>\else<code faux>\fi-\tidx*{ifodd}

qui est vrai si le \verb|<nombre>| est impair.

\showcode|\def\syracuse#1{%��*\syracuse�
       #1% affiche le nombre
       \ifnum#1>1 % si le nombre est >1
               , % afficher une virgule+espace
               \ifodd#1 % s'il est pair�\tidx*{ifodd}�
                       \exparg\syracuse% appeler la macro \syracuse��*\syracuse�
                       {\number\numexpr3*#1+1% avec 3*n+1�\idx*\number\idx*\numexpr�
                       \expandafter\expandafter\expandafter}% apr�s avoir rendu la macro terminale�\idx*{r�cursivit�!terminale}�
               \else % s'il est pair
                       \expandafter\syracuse\expandafter% appeler la macro \syracuse��*\syracuse�
                       {\number\numexpr#1/2% avec n/2
                       \expandafter\expandafter\expandafter}% apr�s avoir rendu la macro terminale
               \fi
       \else% si le nombre est 1
               .% afficher un point
       \fi
}
a) \syracuse{20}\par
b) \syracuse{14}\par
c) \syracuse{99}\par
d) \edef\foo{\syracuse{15}}\meaning\foo��*\syracuse�|

Les \idx\expandafter qui se trouvent � la fin de l'argument de �\syracuse lors de l'appel r�cursif sont d�velopp�s par \idx\numexpr et rendent la r�cursivit� terminale\idx*{r�cursivit�!terminale}. Il est cependant possible d'�crire un code comportant moins d'\idx\expandafter en mettant le test \tidx{ifodd} � l'int�rieur du nombre �valu� par \idx\numexpr :

\showcode|\def\syracuse#1{%��*\syracuse�
       #1% afficher le nombre
       \ifnum#1>1 % si le nombre est >1
               , % afficher une virgule+espace
               \exparg\syracuse{% appeler la macro \syracuse��*\syracuse�
                       \number\numexpr% avec le nombre :�\idx*\number\idx*\numexpr�
                               \ifodd#1 3*#1+1% 3n+1 si #1 est impair�\tidx*{ifodd}�
                               \else #1/2%      n/2 sinon
                               \fi%
                       \expandafter}% avant de rendre la r�cursivit� terminale�\idx*{r�cursivit�!terminale}�
       \else
       .% si #1=1, afficher un point
       \fi
}
a) \syracuse{20}\par
b) \syracuse{14}\par
c) \syracuse{99}\par
d) \edef\foo{\syracuse{15}}\meaning\foo��*\syracuse�|\idx*[ (suite de)|)]{Syracuse}

\subsection{Calculer une factorielle}\idx*[|(]{factorielle (calcul)}
La factorielle d'un nombre entier positif $n$, not�e $n!$, est �gale au produit des $n$ premiers entiers strictement positifs. Par convention $0!=1$.

L'algorithme r�cursif classique est le suivant o� l'on consid�re que l'argument de la macro �\factorielle[|(] est positif ou nul :
\begin{algo}
       \item si \verb|#1|${}={}0$, \verb|\factorielle{0}|${}={}1$;
       \item sinon, \verb|\factorielle{#1}|${}={}$\verb|#1|${}\times{}$\verb|\factorielle{#1-1}|.
\end{algo}
L'algorithme est d'une simplicit� biblique et sa traduction en \TeX{} est imm�diate :

\showcode/\def\factorielle#1{%��*\factorielle�
       \ifnum#1=0 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               {1}% "1" si #1=0}
               {#1*\exparg\factorielle{\number\numexpr#1-1}}% �\idx*\number\idx*\numexpr�
}
a) \factorielle{0}\qquad
b) \factorielle{3}\qquad
c) \edef\foo{\factorielle{8}}\meaning\foo/

La premi�re chose qui saute aux yeux est que l'expression est bien g�n�r�e, mais qu'elle n'est pas �valu�e par un \idx\numexpr.

Pour y rem�dier, l'id�e va �tre de partir d'une macro chapeau qui se chargera de lancer \idx\number{}\idx\numexpr afin de provoquer, par d�veloppement maximal, la g�n�ration de l'enchainement des multiplications obtenu pr�c�demment et son calcul. Cette macro chapeau ajoutera �galement le \idx\relax final pour stopper le calcul effectu� par \idx\numexpr.

\showcode/\catcode`\@11
\def\factorielle#1{%��*\factorielle�
       \number\numexpr\factorielle@i{#1}\relax% appelle \factorielle@i�\idx*\number\idx*\numexpr�
       % en lan�ant le d�veloppement maximal
}
\def\factorielle@i#1{%
       \ifnum#1=0 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               {1}% "1" si #1=
               {#1*\exparg\factorielle@i{\number\numexpr#1-1}}% �\idx*\number\idx*\numexpr�
}
\catcode`\@12
a) \factorielle{0}\qquad
b) \factorielle{3}\qquad
c) \edef\foo{\factorielle{8}}\meaning\foo/�*\factorielle[|)]\idx*[|)]{factorielle (calcul)}

\subsection{Calculer un PGCD}\idx*[|(]{PGCD}
Le c�l�bre algorithme d'\textsc{Euclide}\idx*{algorithme d'Euclide} permet de calculer le plus grand diviseur commun � deux entiers, voici comment proc�der :
\begin{algo}
       \item soit $a$ le plus grand nombre et $b$ le plus petit
       \item effectuer la division euclidienne $a\div b$ et appeler $r$ le reste;
       \item si $r=0$, le PGCD est le diviseur pr�c�dent $b$;
       \item sinon, retourner en 2 en prenant $a\longleftarrow b$ et $b\longleftarrow r$
\end{algo}

Cet algorithme est des plus faciles � traduire en \TeX{}. La macro chapeau �\PGCD[|(], purement d�veloppable, se chargera du point \no1, une macro auxiliaire du point \no2 et une autre macro auxiliaire des deux derniers points. La r�cursivit� se jouera sur les deux macros auxiliaires :

\showcode|\catcode`\@11
\def\PGCD#1#2{%��*\PGCD�
       \ifnum#1<#2 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               {\PGCD@i{#2}{#1}}% si #1<#2, mettre #2 (le  grand) dans le premier argument
               {\PGCD@i{#1}{#2}}%
}

\def\PGCD@i#1#2{% #1=a   #2=b avec a>b
       \exptwoargs\PGCD@ii% appeler la macro r�cursive avec��*\exptwoargs�
                       {\number\numexpr#1-#2*\truncdiv{#1}{#2}}% le reste de a/b��*\truncdiv�
                       {#2}% et le divisieur b
}

\def\PGCD@ii#1#2{% #1=reste r   #2=diviseur b
       \ifnum#1=\z@\expandafter\firstoftwo\else\expandafter\secondoftwo\fi�\idx*\z@�
               {#2}% si le reste est nul, renvoyer b
               {\PGCD@i{#2}{#1}}% sinon, recommencer avec b et r
}
\catcode`\@12
a) \PGCD{120}{75}\qquad
b) \PGCD{64}{180}\qquad
c) \PGCD{145}{64}\qquad
d) \edef\foo{\PGCD{1612}{299}}\meaning\foo|

Il peut �tre utile d'�crire les divisions successives qui permettent d'arriver au r�sultat. Par exemple, si l'on �crit \verb|\calcPGCD{39}{15}|, on aurait les �tapes suivantes :

\begingroup\parskip=0pt
$39=15\times2+9$\par
$15=9\times1+6$\par
$9=6\times1+3$\par
$6=3\times2+0$\par\endgroup

La macro �\calcPGCD se chargera d'afficher les �tapes ci-dessus. Comme il s'agit d'une macro qui produit un r�sultat typographique, il n'y a pas besoin de la rendre purement d�veloppable. Peu de choses changent; un \verb|\edef| stocke le quotient pour �viter de le calculer deux fois et pour chaque ligne de calcul, les nombres sont affich�s lorsqu'ils sont disponibles. Le mode math commence donc dans la premi�re macro auxiliaire et se termine dans la seconde, une fois que le reste a �t� calcul�.

\showcode|\catcode`\@11
\def\calcPGCD#1#2{%��*\calcPGCD�
       \ifhmode\par\fi% si en mode horizontal, former le paragraphe�\tidx*{ifhmode}�
       \ifnum#1<#2 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               {\calcPGCD@i{#2}{#1}}% si #1<#2, mettre #2 (le  grand) dans le premier argument
               {\calcPGCD@i{#1}{#2}}%
}

\def\calcPGCD@i#1#2{% #1=a   #2=b avec a>b
       \edef\calcPGCD@quotient{\number\truncdiv{#1}{#2}}% stocke le quotient
       $#1=\calcPGCD@quotient\times#2% en mode maths, afficher "a=q*b" (� suivre)
       \exptwoargs\calcPGCD@ii% appeler la macro r�cursive avec��*\exptwoargs�
                       {\number\numexpr#1-#2*\calcPGCD@quotient}% le reste de a/b��*\truncdiv�
                       {#2}% et le divisieur b
}

\def\calcPGCD@ii#1#2{% #1=reste r   #2=diviseur b
       +#1$\par% (suite du mode math) afficher "+r", fermer le mode math et \par
       \ifnum#1=\z@\expandafter\firstoftwo\else\expandafter\secondoftwo\fi%�\idx*\z@�
               {}% si le reste est nul, ne rien faire
               {\calcPGCD@i{#2}{#1}}% sinon, recommencer avec b et r
}
\catcode`\@12
\calcPGCD{39}{15}\medbreak�\idx*\medbreak�
\calcPGCD{1612}{299}|

Pour am�liorer la lisibilit� de ces lignes de calcul, un raffinement typographique suppl�mentaire pourrait �tre d'aligner sur une m�me verticale les signes �$=$�, �$\times$� et �$+$�. Comme ces signes sont toujours les m�mes, le meilleur moyen d'y parvenir va �tre de b�tir un alignement avec \idx[|(]\halign o� ces signes feront partie prenante du pr�ambule de fa�on � ne pas �tre �crits � chaque ligne.

Examinons donc tout d'abord le pr�ambule. Il y aura 4 colonnes, chacune �tant r�serv�e � un nombre comme dans

\[39=15\times2+9\]

D�cidons que la premi�re colonne est compos�e au fer � droite (le nombre sera au plus pr�s du signe �$=$�), elle sera d�clar�e \idx*\hfil\verb|$\hfil#$| dans le pr�ambule.

Pour la seconde colonne, nous allons placer le signe �$=$� avant le contenu de la colonne. Il est important de comprendre qu'en mode math�matique\idx*{mode!math�matique}, le signe �$=$� doit �tre pr�c�d� de quelque chose pour qu'une espace math�matique soit ins�r�e avant lui\footnote{Tous les composants d'une formule math�matique sont appel�s \emph{atomes}.

Pour de plus amples informations sur le type d'atomes math�matiques composant une formule (le signe $=$ �tant de type �\textit{Rel}�) et les espaces qu'ils g�n�rent, voir le \TeX book pages 184-185, 200 ainsi que l'annexe~G.} :

\showcode/\frboxsep=0pt % encadrer au plus proche��*\frbox�
\leavevmode\frbox{$=$} n'est pas identique � \frbox{${}={}$}�\idx*\leavevmode�*\frbox�/

En effet, dans le premier cas, ce qui se trouve � gauche de l'atome de relation �$=$� est vide, il n'y a donc aucun espace math�matique qui est ajout�. En revanche, dans la seconde boite, ce qui se trouve � gauche de �$=$� est �\verb|}|� qui est un atome � \textit{Close} � et, en vertu des r�gles expos�es dans le \TeX book, l'espace math�matique ins�r� � gauche de �$=$� devient le m�me qu'avec un atome � \textit{Ord} � comme l'est un chiffre ou une lettre.

La cons�quence de tout cela est que la deuxi�me colonne aura comme pr�ambule

\centrecode-${}=\hfil#$-

\noindent o� le \idx\hfil nous assure que le nombre, repr�sent� par \verb|#|, sera compos� au fer � droite (il sera donc au plus pr�s du signe �$\times$� qui suit).

Puisque les atomes �$\times$� et �$+$� �tant de type \textit{Rel}, le m�me raisonnement doit �tre suivi pour la 3\ieme{} et 4\ieme{} colonnes qui auront comme pr�ambules

\centrecode-${}\times#\hfil$-\idx*\times

\noindent et

\centrecode-${}+#\hfil$-

Un deuxi�me probl�me est qu'une cellule d'un alignement est �quivalente � un groupe. Par cons�quent, pour pouvoir se transmettre dans l'alignement, l'assignation du quotient doit �tre globale. Enfin, le \tidx{ifnum} et le \verb|\fi| doivent se trouver dans la m�me cellule.

\showcode|\catcode`\@11
\def\calcPGCD#1#2{%��*\calcPGCD�
       \vtop{% mettre l'alignement dans une \vtop
               \halign{% les "#" doivent �tre doubl�s puisqu'� l'int�rieur d'une macro�\idx*\halign�
               $\hfil##$&${}=\hfil##$&${}\times##\hfil$&${}+##\hfil$% pr�ambule�\idx*\hfil\idx*\times�
               \cr% fin du pr�ambule et d�but de la premi�re cellule�\idx*\cr�
               \ifnum#1<#2 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
                       {\calcPGCD@i{#2}{#1}}% si #1<#2, mettre #2 (le  grand) dans le premier argument
                       {\calcPGCD@i{#1}{#2}}%
               \crcr% fin de l'alignement�\idx*\crcr�
               }%
       }%
}

\def\calcPGCD@i#1#2{% #1=a   #2=b avec a>b
       \xdef\calcPGCD@quotient{\number\truncdiv{#1}{#2}}% stocke le quotient�\idx*\xdef�
       #1 & \calcPGCD@quotient & #2 &% afficher "a=q*b" (� suivre)
       \exptwoargs\calcPGCD@ii% appeler la macro r�cursive avec��*\exptwoargs�
                       {\number\numexpr#1-#2*\calcPGCD@quotient}% le reste de a/b��*\truncdiv�
                       {#2}% et le divisieur b
}

\def\calcPGCD@ii#1#2{% #1=reste r   #2=diviseur b
       #1% (suite de l'alignement) afficher "+r"
       \cr% et terminer la ligne en cours�\idx*\cr�
       \ifnum#1=\z@\expandafter\firstoftwo\else\expandafter\secondoftwo\fi%�\idx*\z@�
               {}% si le reste est nul, ne rien faire
               {\calcPGCD@i{#2}{#1}}% sinon, recommencer avec b et r
}
\catcode`\@12
a) \calcPGCD{39}{15}\medbreak�\idx*\medbreak�
b) \calcPGCD{1612}{299}|\idx*[|)]\halign�*\PGCD[|)]\idx*[|)]{PGCD}

\subsection{Convertir un nombre en base 2}\idx*[|(]{base (conversion)}
Pour convertir un entier positif $n$ quelconque �crit en base 10 en base $b$, voici l'algorithme � utiliser :

\begin{algo}
       \item effectuer la division de $n$ par $b$. Appeler $q$ est le quotient et $r$ le reste;
       \item si $q\neq 0$, retourner en 1 avec $n\longleftarrow q$;
       \item sinon, le nombre cherch� est constitu� des restes, lus du \emph{dernier au premier}.
\end{algo}

Voici les divisions euclidiennes qu'il faut poser pour convertir 43 en base 2 :
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\makeatletter
\newbox\nb@box
\newcount\nb@a
\newcount\nb@b
\newcount\iter@
\newcommand\division[2][2]{\def\dividende@{#2}\def\base@{#1}\iter@\@ne\division@{#2}{#1}}
\newcommand\division@[2]{%
       \setbox\nb@box\hbox{\kern0.5em#1\kern0.5em}%
       \nb@a#1 \nb@b#1 \divide\nb@b#2
        \vtop{%
               \begingroup
                       \multiply\nb@b#2 \advance\nb@a-\nb@b
                       \hbox to\wd\nb@box{\hfil#1\hfil}%
                       \vskip3pt\hrule height0pt width\wd\nb@box\vskip3.4pt
                       \hbox to\wd\nb@box{\hfil\textbf{\number\nb@a}\kern0.5em}%
                       \expandafter\xdef\csname reste@\number\iter@\endcsname{\number\nb@a}%
               \endgroup}%
       \setbox\nb@box\hbox{8}\vrule height\ht\nb@box depth3.5ex
       \setbox\nb@box\hbox{\kern0.5em\ifnum#2>\nb@b #2\else\number\nb@b\fi\kern0.5em}%
       \vtop{%
               \hbox to\wd\nb@box{\kern0.5em#2\hfil}%
               \vskip3pt\hrule height0.4pt width\wd\nb@box\vskip3pt
               \hbox{%
                       \csname @\ifnum\nb@b>\z@ first\else second\fi oftwo\endcsname
                               {\advance\iter@\@ne\gdef\maxiter{\number\iter@}%\idx*\gdef
                               \expandafter\division@\expandafter{\number\nb@b}{#2}}%
                               {\kern0.5em\number\nb@b\xdef\maxiter{\number\iter@}}}%
               }%
}
\newcommand\afficheresultat[1]{%
       \csname reste@#1\endcsname
       \ifnum#1>\@ne
               \expandafter\afficheresultat
       \else
               \expandafter\@gobble
       \fi{\number\numexpr#1-1}%
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\par\hfill\division{43}\hfill\null
\medbreak

Et donc, en lisant les restes dans l'ordre inverse, le nombre \dividende@{} s'�crit \afficheresultat\maxiter{} en base 2.
\makeatother

Appelons �\baseconv[|(]\verb|{<n>}| la macro qui va convertir en base 2 le nombre \verb|<n>| �crit en base 10. Donnons-nous une difficult� suppl�mentaire de taille : le code devra �tre purement d�veloppable. Ainsi, �crire \verb|\edef\foo{\baseconv{43}}| met dans le texte de remplacement de \verb|\foo| les caract�res \texttt{\afficheresultat\maxiter}.
\grandsaut

Dans un premier temps, nous allons �crire la macro \verb|\baseconv| de fa�on � ce qu'elle �crive les restes dans l'ordre o� ils sont trouv�s. Afin que la macro soit purement d�veloppable, la macro �\truncdiv sera mise � contribution.

\showcode|\catcode`\@11
\def\baseconv#1{%��*\baseconv�
       \unless\ifnum#1=\z@ % si #1 est diff�rent de 0�\tidx*{unless}\idx*\z@�
               \number\numexpr#1-2*\truncdiv{#1}2\relax% �crire le reste�\idx*\number\idx*\numexpr �*\truncdiv\defline\aaa�
               \exparg\baseconv{\number\truncdiv{#1}2\expandafter}% recommencer avec #1/2��*\truncdiv�
       \fi% apr�s que le \fi ait �t� lu
}
\catcode`\@12
a) \baseconv{43}\qquad
b) \baseconv{32}\qquad
c) \edef\foo{\baseconv{159}}\meaning\foo�\idx*\meaning�*\baseconv�|

Cela fonctionne, les restes sont bien �crits au fur et � mesure de leur calcul � la ligne \no\aaa. Certes, la macro pourrait �tre optimis�e puisque �\truncdiv\verb|{#1}2| est calcul� deux fois, mais laissons cela pour l'instant. La question qui se pose est �comment s'y prendre pour inverser l'ordre des restes ?�

L'id�e est de copier la m�thode des � r�servoirs� mise en \oe uvre dans la macro �\reverse programm�e � la page~\pageref{reverse}. Pour ce faire, la macro �\baseconv ne va devenir qu'une macro chapeau qui va transmettre � la vraie macro r�cursive \verb|\baseconv@i| deux arguments non d�limit�s : le premier, vide au d�but, contiendra la liste des restes �crits dans l'ordre d�sir�. Le second sera le nombre \verb|<n>|. Le fonctionnement de cette macro sera des plus simples.

Si \verb|<n>| est nul, l'affichage de l'argument \verb|#1| sera fait. Sinon, la macro \verb|\baseconv@i|

\begin{itemize}
       \item ajoutera \emph{avant} les autres restes le chiffre

       \centrecode/\number\numexpr#2-2*\truncdiv{#2}2\relax/

       \noindent Notons que la primitive \idx\number ne s'applique ici qu'� \idx\numexpr\verb|...|\idx\relax qui a le statut de registre d'entier. Il n'y a donc aucun risque pour \idx\number de lire un entier sup�rieur � $2^{31}-1$ si les autres restes qui sont � la suite sont en grand nombre ;
       \item remplacera l'argument \verb|#2| par \verb|\number\truncdiv{#2}2|;
       \item une fois ceci fait, elle s'appellera elle-m�me.
\end{itemize}

\showcode|\catcode`\@11
\def\baseconv#1{%��*\baseconv�
       \baseconv@i{}{#1}%
}

\def\baseconv@i#1#2{% #1=restes   #2=n
       \ifnum#2=\z@\expandafter\firstoftwo\else\expandafter\secondoftwo\fi% si n=0
               {#1}% si <n>=0, afficher tous les restes
               {% sinon, recommencer en
               \exptwoargs\baseconv@i% ajoutant le reste courant avant #1��*\exptwoargs�
                       {\number\numexpr#2-2*\truncdiv{#2}2\relax #1}
                       {\number\truncdiv{#2}2}% et en prenant n:=n/2��*\truncdiv�
               }%
}

\catcode`\@12
a) \baseconv{43}\qquad
b) \baseconv{32}\qquad
c) \edef\foo{\baseconv{159}}\meaning\foo|

\subsection{Aller vers des bases plus �lev�es}
Pourquoi ne pas aller plus loin et convertir un nombre en une base arbitraire ? La limitation r�side dans le fait que les symboles utilis�s pour les chiffres ne sont pas extensibles � l'infini. Nous avons les 10 chiffres et les 26 lettres (que nous prendrons majuscules) ce qui nous fait 36 signes diff�rents, que nous appellerons � \verb|<chiffre>| �. Nous allons donc d'embl�e nous limiter � une conversion vers une base inf�rieure ou �gale � 36.

Le premier travail est de construire une macro �\basedigit, purement d�veloppable, de syntaxe

\centrecode|\basedigit{<nombre>}|

\noindent qui se d�veloppe en un \verb|<chiffre>| selon le \verb|<nombre>| inf�rieur � 36 pass� en argument. La m�thode b�te et m�chante du \tidx{ifcase} et des 36 \tidx{or} va �tre privil�gi�e ici.

Pour que le \verb|<chiffre>| puisse �tre facilement accessible, l'ensemble

\centrecode-\romannumeral\basedigit{<nombre>}-

\noindent doit donner le \verb|<chiffre>| par 1-d�veloppement du \idx\romannumeral. Cela implique de 1-d�velopper les \tidx{or} restants et le \verb|\fi| avant que \idx\romannumeral ait fini son travail :

\showcode/\catcode`\@11
\def\z@@{\expandafter\z@\expandafter}�\idx*\z@�
\def\basedigit#1{%�\tidx*{ifcase}�*\basedigit�
       \ifcase#1
               \z@@ 0%
               \or\z@@ 1\or\z@@ 2\or\z@@ 3\or\z@@ 4\or\z@@ 5\or\z@@ 6\or\z@@ 7%�\tidx*{or}�
               \or\z@@ 8\or\z@@ 9\or\z@@ A\or\z@@ B\or\z@@ C\or\z@@ D\or\z@@ E%
               \or\z@@ F\or\z@@ G\or\z@@ H\or\z@@ I\or\z@@ J\or\z@@ K\or\z@@ L%
               \or\z@@ M\or\z@@ N\or\z@@ O\or\z@@ P\or\z@@ Q\or\z@@ R\or\z@@ S%
               \or\z@@ T\or\z@@ U\or\z@@ V\or\z@@ W\or\z@@ X\or\z@@ Y\or\z@@ Z%�\tidx*{or}�
       \fi
}
\long\def\>#1<{\detokenize{#1}}�\idx*\long\idx*\detokenize�
a) \expandafter\>\romannumeral\basedigit{23}<\quad�\idx*\romannumeral�
b) \expandafter\>\romannumeral\basedigit{6}<�\idx*\romannumeral�*\basedigit�
\catcode`@12/

Le test \tidx{ifcase}\verb|<n>|, d�velopp� par \idx\romannumeral, avale tout jusqu'au \verb|<n>|\ieme{} \tidx{or}. Par exemple, si l'argument \verb|<n>| est 3, \idx\romannumeral va d�velopper le test et trouver ceci :

\centrecode-\z@@ C\or \z@@ D......\fi-

\noindent La macro \verb|\z@@| sera 1-d�velopp�e et \idx\romannumeral va voir

\centrecode-\expandafter\z@\expandafter C\or \z@@ D......\fi-

\noindent \idx\romannumeral poursuit le d�veloppement puisque n'ayant toujours pas trouv� de nombre. Le pont d'\idx\expandafter va 1-d�velopper �\verb|\or \z@@ D...\fi|�, faisant disparaitre le tout. Il va rester

\centrecode-\z@ C-\idx*\z@

\noindent Ensuite, le \idx\z@ va stopper la lecture du nombre par \idx\romannumeral, laissant �\verb|C|�.
\grandsaut

Pour que la macro �\baseconv reste purement d�veloppable, il va falloir lui transmettre � chaque it�ration tous les arguments dont elle a besoin et en particulier la base, qui sera un argument fig� et lu � chaque fois.

De plus, pour �viter que � \truncdiv\verb|{<n>}{<b>}| soit calcul� deux fois, ce quotient, une fois calcul�, sera transmis comme argument suppl�mentaire � une autre sous macro.

Voici le code complet :

\showcode|\catcode`\@11
\def\baseconv#1#2{% #1=base  #2=nombre � convertir��*\baseconv�
       \ifnum#1<37 % base maxi = 36 (10 signes chiffres + 26 signes lettres)
               \antefi��*\antefi�
               \baseconv@i{}{#2}{#1}%
       \fi
}
\def\baseconv@i#1#2#3{% #1=restes  #2=n  #3=base
       \ifnum#2=\z@ \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               {#1}% si n=0, afficher tous les restes
               {% si non, transmettre en dernier argument
               \expsecond{\baseconv@ii{#1}{#2}{#3}}%��*\expsecond�
                       {\number\truncdiv{#2}{#3}}% le quotient��*\truncdiv�
               }%
}
\def\baseconv@ii#1#2#3#4{% #1=restes  #2=n  #3=base  #4=q
       \exparg\baseconv@i% recommencer, en ajoutant le <chiffre> avant les restes
               {\romannumeral\basedigit{\number\numexpr#2-#4*#3\relax}#1}%�\idx*\romannumeral�*\basedigit�
               {#4}% et en rempla�ant n par q
               {#3}%
}
\def\z@@{\expandafter\z@\expandafter}%�\idx*\z@�
\def\basedigit#1{%�\tidx*{ifcase}�*\basedigit�
       \ifcase#1
               \z@@ 0%
               \or\z@@ 1\or\z@@ 2\or\z@@ 3\or\z@@ 4\or\z@@ 5\or\z@@ 6\or\z@@ 7%�\tidx*{or}�
               \or\z@@ 8\or\z@@ 9\or\z@@ A\or\z@@ B\or\z@@ C\or\z@@ D\or\z@@ E%
               \or\z@@ F\or\z@@ G\or\z@@ H\or\z@@ I\or\z@@ J\or\z@@ K\or\z@@ L%
               \or\z@@ M\or\z@@ N\or\z@@ O\or\z@@ P\or\z@@ Q\or\z@@ R\or\z@@ S%
               \or\z@@ T\or\z@@ U\or\z@@ V\or\z@@ W\or\z@@ X\or\z@@ Y\or\z@@ Z%�\tidx*{or}�
       \fi
}
\catcode`\@12
a) "\baseconv{20}{21587}"\qquad
b) "\baseconv{16}{32}"\qquad
c) \edef\foo{\baseconv{16}{159}}%
  "\meaning\foo"\qquad�\idx*\meaning�
d) "\baseconv{2}{43}"��*\baseconv�|�*\baseconv[|)]\idx*[|)]{base (conversion)}

\section{Macros manipulant les listes}\idx*[|(]{liste d'�l�ments}
Donnons-nous la d�finition suivante : une � liste � est une collection ordonn�e d'� �l�ments � s�par�s les uns des autres par un � s�parateur � que nous prendrons �gal � la virgule. Un � �l�ment � est un ensemble de tokens o� les accolades �ventuelles qui le composent sont �quilibr�es et qui ne contient pas le s�parateur, sauf si celui-ci est entre accolades.

Le but est d'ex�cuter les actions suivantes sur une liste donn�e : trouver un �l�ment par son num�ro, trouver le num�ro d'un �l�ment, supprimer un �l�ment, le d�placer, ins�rer un �l�ment � une position, et � ex�cuter � la liste, c'est-�-dire que chaque �l�ment deviendra l'argument d'une macro et le code obtenu sera lu par \TeX{}.

Une liste est stock�e par \verb|\def| dans le texte de remplacement d'une macro. Une telle macro recevra le nom de \verb|\<macrolist>|.

\subsection{Trouver un �l�ment d'une liste}�*\finditem[|(]
Trouver le \verb|<n>|\ieme{} �l�ment se fera � l'aide de la macro �\finditem selon cette syntaxe:

\centrecode-\finditem\<macrolist>{<n>}-

\noindent Le \verb|<n>|\ieme{} �l�ment de la liste sera renvoy�. La macro sera purement d�veloppable, sous r�serve que l'�l�ment renvoy� le soit.

Du c�t� de la mise en \oe uvre, nous utiliserons la m�thode classique : la macro �\finditem sera une macro chapeau. Afin qu'elle soit purement d�veloppable, la macro r�cursive \verb|\finditem@i| doit recevoir � chaque it�ration \emph{tous} les param�tres dont elle a besoin sous forme d'arguments, c'est-�-dire

\begin{enumerate}
       \item la position courante, initialis�e � 1 par la macro chapeau et incr�ment�e � chaque it�ration;
       \item la position de l'�l�ment � trouver;
       \item l'�l�ment courant qui pr�c�de le reste de la liste, que la macro chapeau aura pris soin de terminer par une virgule et un quark.
\end{enumerate}

Le travail de la macro consistera en deux tests imbriqu�s. Le premier qui regardera si la liste est arriv�e � sa fin (en comparant l'�l�ment courant au quark) et l'autre si la position courante correspond � la position cherch�e.

\showcode|\catcode`\@11
\def\quark@list{\quark@list}% quark de fin de liste
\def\finditem#1{% #1 = \<macrolist>, la position est lue plus tard par \finditem@i��*\finditem�
       \exparg\finditem@i{#1}% 1-d�veloppe la \<macrolist>��*\exparg�
}
\def\finditem@i#1#2{% #1 = liste   #2=position cherch�e
       \finditem@ii{1}{#2}#1,\quark@list,% appelle la macro r�cursive
}
\def\finditem@ii#1#2#3,{% #1=position courante  #2=position cherch�e  #3=�l�ment courant
       \ifx\quark@list#3\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               {}% si la fin de liste est atteinte, ne rien renvoyer
               {% sinon
               \ifnum#1=#2 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
                       {% si la position est la bonne
                       \finditem@iii{#3}% renvoyer #3 et manger les �l�ments restants
                       }
                       {% si la position n'est pas la bonne, recommencer en incr�mentant #1
                       \exparg\finditem@ii{\number\numexpr#1+1}{#2}%��*\exparg�
                       }%
               }%
}
\def\finditem@iii#1#2\quark@list,{% renvoyer #1 et manger le reste de la liste
       #1%�\defline\aaa�
}
\catcode`\@12
\def\liste{a,bcd,{ef},g,hij,kl}
a) \edef\foo{\finditem\liste5}\meaning\foo\qquad
b) \edef\bar{\finditem\liste3}\meaning\bar|

L'�l�ment �\verb|{ef}|� est d�pouill� de ses accolades lorsqu'il est lu par la macro r�cursive \verb|\finditem@ii|. Pour nous pr�munir de cette erreur, nous devons ins�rer un token (nous prendrons \idx\relax) avant chaque �l�ment, et supprimer ce \idx\relax � chaque fois que figure l'�l�ment \verb|#3| dans la macro \verb|\finditem@ii|, ainsi qu'� la ligne \no\aaa{} o� il est l'argument \verb|#1| de la macro.

De plus, nous allons aussi d�finir une macro �\finditemtocs, qui assignera l'�l�ment trouv� � une macro selon la syntaxe

\centrecode-\finditemtocs\<macrolist>{<n>}\<macro>-

Comme cette variante n'a pas � �tre purement d�veloppable, il lui suffira de d�finir \verb|\finditemtocs@ii| pour ex�cuter une l'assignation. Tout le reste sera identique � �\finditem.

\showcode/\catcode`\@11
\def\quark@list{\quark@list}% quark de fin de liste
\def\finditem#1{% #1 = \<macro>, la position est lue plus tard par \finditem@i
       \exparg\finditem@i{#1}% 1-d�veloppe la \<macro>��*\exparg�
}
\def\finditem@i#1#2{% #1 = liste   #2=position cherch�e��*\finditem�
       \ifnum#2>\z@% ne faire quelque chose que si la position est >0
               \antefi��*\antefi�
               \finditem@ii{1}{#2}\relax#1,\quark@list,% appelle la macro r�cursive
       \fi
}
\def\finditem@ii#1#2#3,{% #1=position courante  #2=position cherch�  #3=�l�ment courant
       \expandafter\ifx\expandafter\quark@list\gobone#3%
       \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               {}% si la fin de liste est atteinte, ne rien renvoyer
               {% sinon
               \ifnum#1=#2 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
                       {% si la position est la bonne
                       \finditem@iii{#3}% renvoyer #3 et manger les �l�ments restants
                       }
                       {% si la position n'est pas la bonne, recommencer en incr�mentant #1
                       \exparg\finditem@ii{\number\numexpr#1+1}{#2}\relax��*\exparg�
                       }%
               }%
}
\def\finditem@iii#1#2\quark@list,{% renvoyer #1 et manger le reste de la liste
       \gobone#1%�\defline\aaa�
}
\def\finditemtocs#1#2#3{% #1 = \<macro>  #2=position  #3=macro � d�finir��*\finditemtocs�
       \def\finditemtocs@iii##1##2\quark@list,{% renvoyer #1 et manger le reste de la liste
               \expandafter\def\expandafter#3\expandafter{\gobone##1}%�\defline\aaa�
       }%
       \let#3=\empty�\idx*\empty�
       \exparg\finditemtocs@i{#1}{#2}% 1-d�veloppe la \<macro>��*\exparg�
}
\def\finditemtocs@i#1#2{% #1 = liste   #2=position cherch�e
       \ifnum#2>\z@% ne faire quelque chose que si la position est >0�\idx*\z@�
               \antefi\finditemtocs@ii{1}{#2}\relax#1,\quark@list,% appelle la macro r�cursive��*\antefi�
       \fi
}
\def\finditemtocs@ii#1#2#3,{%
% #1=position courante  #2=position cherch�  #3=\relax + �l�ment courant
       \expandafter\ifx\expandafter\quark@list\gobone#3%
       \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               {}% si fin de liste ne rien faire. Sinon, si position bonne
               {\ifnum#1=#2 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
                       {\finditemtocs@iii{#3}% renvoyer #3 et manger les �l�ments restants
                       }% si la position n'est pas la bonne, recommencer en incr�mentant #1
                       {\exparg\finditemtocs@ii{\number\numexpr#1+1}{#2}\relax%��*\exparg�
                       }%
               }%
}
\catcode`\@12
\def\liste{a,bcd,{ef},g,hij,kl}
a) "\finditem\liste5"\qquad
b) \edef\bar{\finditem\liste3}\meaning\bar\qquad
c) \finditemtocs\liste{3}\foo\meaning\foo��*\finditemtocs�/�*\finditem[|)]

\subsection{Trouver la position d'un �l�ment}
Il faut annoncer la couleur d'entr�e : la macro �\positem, charg�e de trouver la position d'un �l�ment et de syntaxe

\centrecode-\positem\<macrolist>{<�l�ment>}-

\noindent ne sera pas purement d�veloppable. En effet, il faudra comparer l'�l�ment courant � l'�l�ment cherch� et pour ce faire, un test \verb|\ifx| comparera deux macros contenant ces �l�ments. D�finir ces macros rend donc la macro non d�veloppable.

Si l'�l�ment cherch� n'est pas dans la liste, la position renvoy�e sera �gale 0.
\grandsaut

� nouveau, une variante �\positemtocs sera programm�e. Toutefois, nous allons essayer de ne pas proc�der comme avec �\finditem et ne pas r��crire presque compl�tement le code de la macro �\positem en modifiant deux ou trois choses, ce qui est lourd et assez maladroit. Il est possible de faire mieux. Pour cela, il faut d�finir ce que l'on appelle en programmation un �\emph{\idx[ (m�thode de programmation)]{hook}}�. Un hook est un appel � une macro que l'on met � certains endroits du code afin d'ex�cuter l'action faite par la macro. Pour modifier cette action, il suffit de reprogrammer le hook et non pas r��crire des portions enti�res du code initial.

Dans le cas pr�sent, le hook sera nomm� �\verb|\positem@endprocess|�. Pour la macro �\positem, se hook sera d�fini pour donner la position, pr�alablement calcul�e et stock�e dans la macro \verb|\pos@item|. Le hook sera donc d�fini par

\centrecode-\def\positem@endprocess{\pos@item}-

Pour la macro �\positemtocs, ce \idx[ (m�thode de programmation)]{hook} sera programm� pour rendre la macro � d�finir \verb|\let|-�gale � \verb|\pos@item|.

\showcode/\catcode`\@11
\def\quark@list{\quark@list}% quark de fin de liste
\def\positem#1{% #1 = \<macrolist>, la position est lue plus tard par \positem@i��*\positem�
       \def\positem@endprocess{\pos@item}% hook : afficher la position�\idx*[ (m�thode de programmation)]{hook}�
       \exparg\positem@i{#1}% 1-d�veloppe la \<macrolist>��*\exparg�
}
\def\positem@i#1#2{% #1 = liste   #2=�l�ment cherch�
       \def\sought@item{#2}% d�finir l'�l�ment cherch�
       \positem@ii{1}\relax#1,\quark@list,% appelle la macro r�cursive
}
\def\positem@ii#1#2,{% #1=position courante  #2=\relax + �l�ment courant
       \expandafter\def\expandafter\current@item\expandafter{\gobone#2}%
       \ifx\current@item\quark@list\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               {\def\pos@item{0}% si la fin de liste est atteinte, renvoyer 0
               \positem@endprocess% et aller au hook
               }% sinon
               {\ifx\current@item\sought@item\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
                       {\def\pos@item{#1}% si la position est la bonne, d�finir la position
                       \positem@goblist% et manger les �l�ments restants
                       }% si la position n'est pas la bonne, recommencer en incr�mentant #1
                       {\exparg\positem@ii{\number\numexpr#1+1}\relax��*\exparg�
                       }%
               }%
}
\def\positem@goblist#1\quark@list,{\positem@endprocess}% manger la liste et aller au hook

\def\positemtocs#1#2#3{% #1=\<macrolist>  #2=�l�ment � chercher  #3=macro � d�finir��*\positemtocs�
       \def\positem@endprocess{\let#3=\pos@item}% hook : mettre le r�sultat dans #3�\idx*[ (m�thode de programmation)]{hook}�
       \exparg\positem@i{#1}{#2}% 1-d�veloppe la \<macrolist>��*\exparg�
}

\catcode`\@12
\def\liste{a,bcd,{ef},g,hij,,kl}
a) \positem\liste{g}\qquad
b) \positem\liste{ef}\qquad
c) \positem\liste{{ef}}\qquad
d) \positem\liste{}\medbreak��*\positem�

\def\liste{a,bcd,{ef},g,hij,,kl}
a) \positemtocs\liste{g}\foo\meaning\foo\qquad
b) \positemtocs\liste{ef}\foo\meaning\foo\qquad
c) \positemtocs\liste{{ef}}\foo\meaning\foo\qquad
d) \positemtocs\liste{}\foo\meaning\foo\qquad��*\positemtocs�/

\subsection{Ins�rer un �l�ment dans une liste}�*\insitem[|(]
Passons maintenant � la macro �\insitem qui ins�re un �l�ment dans une liste � une position sp�cifi�e, position qui sera la position de l'�l�ment dans la liste modifi�e apr�s l'insertion

\centrecode-\insitem\<macrolist>{<position>}{<�l�ment>}-

Si la \verb|<position>| est inf�rieure ou �gale � 1, l'�l�ment devra �tre ins�r� � la premi�re position. Si la \verb|<position>| est strictement sup�rieure � la longueur de la liste, l'�l�ment viendra en derni�re position. Remarquons que rendre la macro �\insitem purement d�veloppable serait un non-sens puisqu'elle n'a pas vocation � renvoyer quelque chose, mais modifie la \verb|\<macrolist>| qui contient la liste d'�l�ments.

Nous allons proc�der un peu comme avec �\finditem, mais nous stockerons  dans une macro temporaire \verb|\item@list| les �l�ments mang�s en y ajoutant l'�l�ment � ins�rer lorsque la position voulue est atteinte. Par ailleurs, la macro r�cursive sera �crite comme une sous-macro de �\insitem afin de pouvoir facilement acc�der � ses arguments.

\showcode/\catcode`\@11
\def\quark@list{\quark@list}% quark de fin de liste
\def\insitem#1#2#3{% #1 = macro   #2=position cherch�e   #3=�l�ment � ins�rer
       \let\item@list=\empty
       \ifnum#2<1 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               % si position < 1
               {\addtomacro\item@list{#3,}% ajouter l'�lement � ins�rer en premier
               \eaddtomacro\item@list#1% puis la liste enti�re
               }
               % si la position  > 1
               {% d�finir la macro r�cursive
               \def\insitem@i##1##2,{% ##1 = position courante  ##2=\relax + �l�ment courant
                       \expandafter\ifx\expandafter\quark@list\gobone##2%
                       \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
                               {\addtomacro\item@list{#3}}% si fin de liste, ajouter l'�l�ment en dernier
                               {% sinon, si la position cherch�e est atteinte
                               \ifnum##1=#2 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
                                       {\addtomacro\item@list{#3,}% ajouter l'�lement
                                       \add@remainlist##2,% et ##2 (en supprimant le \relax) et le reste
                                       }% si la position n'est pas atteinte
                                       {\eaddtomacro\item@list{\gobone##2,}% ajouter l'�l�ment
                                       \exparg\insitem@i{\number\numexpr##1+1}\relax% et recommencer
                                       }%
                               }%
                       }%
               % appel de la macro r�cursive
               \expandafter\insitem@i\expandafter1\expandafter\relax#1,\quark@list,%
               }%
       \let#1=\item@list% rendre #1 �gal au r�sultat
}

\def\add@remainlist#1,\quark@list,{%
       \eaddtomacro\item@list{\gobone#1}% ajouter #1 ainsi que les autres
}
\catcode`\@12
\def\liste{a,bra,{cA},da,brA}\insitem\liste3{XX}\meaning\liste\par
\def\liste{a,bra,{cA},da,brA}\insitem\liste0{XX}\meaning\liste\par
\def\liste{a,bra,{cA},da,brA}\insitem\liste9{XX}\meaning\liste��*\insitem�/�*\insitem[|)]

\subsection{Supprimer un �l�ment}
Pour supprimer un �l�ment de la liste donn� par son num�ro avec �\delitem, nous allons agir comme ci-dessus avec la diff�rence suivante : si la position est strictement inf�rieure � 1 ou strictement sup�rieure au num�ro du dernier �l�ment, ne rien faire.

Supprimer un �l�ment va �tre un peu plus difficile qu'en ins�rer un. La difficult� vient du fait que lorsqu'on lit un �l�ment, on lit aussi la virgule qui le suit puisqu'elle agit comme d�limiteur de la macro r�cursive. Si l'�l�ment � supprimer est le dernier de la liste, il restera donc � lire le quark et la virgule qui sont ins�r�s � l'appel de la macro r�cursive. On ne peut donc pas d�finir la macro \verb|\add@remainlist| avec un d�limiteur �\verb|,\quark@list,|� mais avec ce d�limiteur-l� : �\verb|\quark@list,|�. Nous la nommerons \verb|\add@reaminingitems|.

\showcode/\catcode`\@11
\def\quark@list{\quark@list}% quark de fin de liste
\def\delitem#1#2{% #1 = macro   #2=position cherch�e��*\delitem�
       \ifnum#2>0 % ne faire quelque chose que si la position est >0
               \def\delitem@i##1##2,{% ##1 = position courante  ##2=\relax + �l�ment courant
                       \expandafter\ifx\expandafter\quark@list\gobone##2%
                       \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
                               {}% si fin de liste, ne rien faire�\defline\ccc�
                               {% sinon, si la position cherch�e est atteinte
                               \ifnum##1=#2 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
                                       {\add@reaminingitems% et ##2 (en supprimant le \relax) et le reste
                                       }% si la position n'est pas la bonne
                                       {\eaddtomacro\item@list{\gobone##2,}% ajouter l'�l�ment��*\eaddtomacro\defline\bbb�
                                       \exparg\delitem@i{\number\numexpr##1+1}\relax% et recommencer��*\exparg�
                                       }%
                               }%
                       }%
               \let\item@list=\empty% initialiser la macro tempporaire
               % appel de la macro r�cursive
               \expandafter\delitem@i\expandafter1\expandafter\relax#1,\quark@list,%�\defline\aaa�
               \let#1=\item@list% rendre #1 �gal au r�sultat
       \fi
}

\def\add@reaminingitems#1\quark@list,{%
       \eaddtomacro\item@list{#1}% ajouter tout jusqu'au quark
}
\catcode`\@12
\for\xx=0 to 8 \do{%��*\for�
\def\liste{a,bcd,{ef},g,hij,kl}
position \xx{} : \expandafter\delitem\expandafter\liste\xx\meaning\liste.\par
}/

Nous le constatons, mais il fallait s'y attendre : une virgule parasite se trouve � la fin de chaque liste trait�e par la macro. Si l'�l�ment � supprimer n'est pas le dernier, cette virgule provient de la ligne \no\aaa{} o� elle est ins�r�e avant le quark et non mang�e par la macro \verb|\add@reaminingitems|. En revanche, si l'�l�ment � supprimer est le dernier, cette virgule provient de la ligne \no\bbb{} o� elle a �t� ins�r�e � l'it�ration pr�c�dente.

Dans tous les cas, il nous faut trouver un moyen de supprimer cette virgule. Le moyen le plus rapide est de d�finir une macro

\centrecode|\def\remove@lastcomma#1,\@nil{\def\item@list{#1}}|

Il faut s'assurer que cette macro re�oit le texte de remplacement de \verb|\item@list| (qui se finit par une virgule dont on veut  se d�barrasser) suivi d'un \verb|\@nil|. Il faut donc ins�rer la ligne suivante juste apr�s la ligne \no\aaa{} de la macro �\delitem :

\centrecode-\expandafter\remove@lastcomma\item@list\@nil-

\subsection{D�placer un �l�ment}
Pour d�placer un item d'une position $x$ � une position $y$, il faut d�j� isoler cet item avec �\finditemtocs, le supprimer avec �\delitem et enfin l'ins�rer avec �\insitem � la position $y$.

\showcode/\catcode`\@11
\def\moveitem#1#2#3{% #1 = liste, #2=position d�part, #3=position arriv�e��*\moveitem�
       \ifnum#2>0 % ne faire quemque chose que si #2>0
               \finditemtocs#1{#2}\temp@item% sauvegarder l'�l�ment��*\finditemtocs�
               \delitem#1{#2}% supprimer l'�l�ment��*\delitem�
               \expsecond{\insitem#1{#3}}\temp@item% ins�rer l'�l�ment��*\expsecond�*\insitem�
       \fi
}
\catcode`\@12
% d�place "b" en 5e position
a) \def\liste{a,b,c,d,e,f} \moveitem\liste25 "\liste"\par
% d�place "d" en 1e position
b) \def\liste{a,b,c,d,e,f} \moveitem\liste41 "\liste"\par
% d�place "c" en 9e position
c) \def\liste{a,b,c,d,e,f} \moveitem\liste39 \liste"\par
% position d�part=0 -> sans effet
d) \def\liste{a,b,c,d,e,f} \moveitem\liste02 "\liste"��*\moveitem�/

\subsection{Ex�cuter une liste}
La derni�re chose qu'il nous reste � faire est d'ex�cuter une liste et pour ce faire, programmer une macro �\runlist. Pour cela, chacun des �l�ments de la liste sera plac� dans l'argument d'une \verb|\<macro>|. Donnons-nous cette syntaxe :

\centrecode-\runlist{\<macrolist>}\with\<macro>-�*\runlist

\noindent Tous les �l�ments de la \verb|<liste>| seront plac�s tour � tour dans l'argument d'une \verb|\<macro>| acceptant un seul argument, et tout se passera comme si nous avions �crit

\centrecode-\<macro>{<�l�ment 1>}\<macro>{<�l�ment 2>}...\<macro>{<�l�ment n>}-

\noindent et que ce code soit ex�cut� par \TeX.

La m�thode consiste � manger chaque �l�ment, l'�crire comme argument de la \verb|\<macro>| et s'arr�ter lorsque la fin de la liste est atteinte. Il va donc falloir stoker dans une macro auxiliaire nomm�e \verb|\collect@run| les \verb|\<macro>{<�l�ment i>}| au fur et � mesure que les �l�ments seront rencontr�s et ex�cuter cette macro � la toute fin du processus. Pour �tre tout � fait propre en programmation, nous allons effectuer la collecte dans un groupe semi-simple de telle sorte que la macro \verb|\collect@run| soit locale � ce groupe et n'existe plus ensuite, �tant entendu que \verb|\collect@run| doit �tre ex�cut�e \emph{hors} du groupe semi-simple.

\showcode/\catcode`\@11
\def\runlist#1\with#2{% #1=liste #2=macro��*\runlist�
       \def\runlist@i##1,{%
               \ifx\quark@list##1\relax\else% si la fin n'est pas atteinte
                       \addtomacro\collect@run{#2{##1}}% ajouter "\<macro>{<�l�ment>}""��*\addtomacro�
                       \expandafter\runlist@i% et recommencer en lisant l'�l�ment suivant
               \fi
       }%
       \begingroup% fait la collecte dans un groupe
               \let\collect@run=\empty% initialiser la macro�\defline\bbb�
               \expandafter\runlist@i#1,\quark@list,% appeler \runlist@i
       \expandafter\endgroup% ferme le groupe et d�truit \collect@run�\defline\aaa�
       \collect@run% apr�s l'avoir d�velopp� !
}
\catcode`\@12
\newcount\foocnt
\foocnt=0 % compteur utilis� pour num�roter les �l�ments dans la macro \foo�\idx*\newcount��\idx*\long�
\def\foo#1{% la macro qui va ex�cuter chaque �l�ment de la liste. #1 = l'�l�ment
       \advance\foocnt1 % incr�mente le compteur�\idx*\advance�
       L'argument \number\foocnt\ est : {\bf #1}\par%�\idx*\number�
}
\def\liste{a,bra,ca,da,BRA}%
\runlist\liste\with\foo%��*\runlist�/

Remarquons l'astuce � la ligne \no\aaa{} qui consiste � � sauter � le \idx\endgroup � l'aide d'un un \idx\expandafter pour 1-d�velopper la macro \verb|\collect@run| avant que le \idx\endgroup ne la d�truise ! C'est une astuce assez commune que de sauter une fin de groupe avec un ou plusieurs \idx\expandafter pour gagner le territoire se trouvant � l'ext�rieur du groupe tout en restant impr�gn� de ses propri�t�s. Cette m�thode permet donc � peu de frais\footnote{Tout au plus quelques \texttt{\string\expandafter} avant le \texttt{\string\endgroup} �ventuellement relay�s � l'ext�rieur du groupe par d'autres \texttt{\string\expandafter} ou tout autre proc�d� permettant de propager le d�veloppement jusqu'au lieu o� l'on veut exporter les propri�t�s du groupe.} d'exporter au dehors de son territoire les propri�t�s d'un groupe avant sa fermeture.

Ici, nous aurions pu proc�der autrement et initialiser \verb|\collet@run| de cette fa�on � la ligne \no\bbb{}

\centrecode-\def\collect@run{\endgroup}-

\noindent et �crire en lieu et place des lignes \nos\aaa-\number\numexpr\aaa+1\relax{} un simple \verb|\collect@run| qui, en se d�veloppant, aurait fait apparaitre le \idx\endgroup au d�but de son texte de remplacement qui aurait provoqu� sa destruction.

\subsection{Enlever les espaces extr�mes}
Il nous reste un dernier pas � accomplir, celui de se jouer des espaces laiss�s avant ou apr�s les �l�ments d'une liste. En effet, il serait commode de saisir

\centrecodespc-\def\liste{ a, b c , def,   g h, ij }-

\noindent et de disposer d'une macro �\sanitizelist\verb|\liste| qui rendrait la liste �gale �

\centrecodespc-a,b c,def,g h,ij-

Cette macro �\sanitizelist supposerait qu'il existe une macro capable de retirer \emph{tous} les espaces qui se trouvent au d�but ou � la fin d'un argument, sans �videmment toucher aux espaces �int�rieurs�.

\subsubsection{Supprimer les espaces du d�but}
La mise au point d'une macro �\removefirstspaces qui retire tous les espaces qui se trouvent au \emph{d�but} de son argument demande tout d'abord de programmer un test �\ifspacefirst\verb|{<texte>}{<vrai>}{<faux>}| qui est vrai si son premier argument commence par un espace. Pour �viter d'envisager le cas d'un \verb|<texte>| vide, la lettre �\verb|W|� sera ajout�e � la fin de cet argument.

\showcode/\catcode`\@11
\def\ifspacefirst#1{%��*\ifspacefirst�
       \expandafter\ifspacefirst@i\detokenize{#1W} \@nil% "W" se pr�munit d'un argument vide
}
\def\ifspacefirst@i#1 #2\@nil{\ifempty{#1}}% renvoyer vrai s'il n'y a rien avant " "��*\ifempty�
\catcode`\@12
a) \ifspacefirst{a bc d}{vrai}{faux}\qquad
b) \ifspacefirst{ a bc d}{vrai}{faux}\qquad
c) \ifspacefirst{ }{vrai}{faux}\qquad
d) \ifspacefirst{}{vrai}{faux}\qquad
e) \ifspacefirst{{ } }{vrai}{faux}\qquad
f) \ifspacefirst{ {x} }{vrai}{faux}��*\ifspacefirst�/

Le c�t� pratique de \idx\detokenize est qu'il permet des accolades dans le \verb|<texte>| malgr� le fait que ce \verb|<texte>| soit l'argument d'une macro � argument d�limit�.

La m�thode mise en \oe uvre sera simple : pour supprimer tous les espaces au d�but d'un argument, il faut tester s'il commence par un espace et dans l'affirmative, manger cet espace avec une macro �\gobspace puis recommencer avec ce qui a �t� obtenu. La macro �\gobspace attendra donc un espace juste apr�s elle et sera donc d�limit�e par un espace. Pour la d�finir, il n'est pas possible d'�crire

\centrecodespc|\def\gobspace {}|

\noindent car dans le code source, un espace qui suit une s�quence de contr�le est ignor� (voir r�gle page~\pageref{regle.espace}). Pour contourner cette r�gle, nous allons mettre en place un pont d'\idx\expandafter pour 1-d�velopper \idx\space en \verb*| | avant que \idx\def n'entre en action :

\showcode/\catcode`\@11
\expandafter\def\expandafter\gobspace\space{}��*\gobspace\idx*\space�

\def\removefirstspaces#1{%��*\removefirstspaces�
       \ifspacefirst{#1}% si #1 commence par un espace��*\ifspacefirst�
               {\exparg\removefirstspaces{\gobspace#1}}% recommencer sans le 1er espace��*\gobspace�
               {#1}% sinon, renvoyer l'argument�\defline\aaa�
}
\catcode`\@12
a) "\removefirstspaces{12 {\bf3}4 567}"\qquad
b) "\removefirstspaces{ 12 {\bf3}4 567}"\qquad
c) \edef\foo{\space\space\space 12 34 567}�\idx*\space�
  "\exparg\removefirstspaces\foo"��*\expsecond�*\removefirstspaces�/

Le dernier cas permet de v�rifier que la r�cursivit� fonctionne lorsque le texte de remplacement de \verb|\foo| commence par \emph{trois} espaces, chacun issu du d�veloppement de \idx\space.

Essayons d'aller un peu plus loin et faisons en sorte que cette macro se d�veloppe en un nombre connu de fois. Nous allons recourir � un \idx\romannumeral, plac� au tout d�but du texte de remplacement de  �\removefirstspaces afin de lancer le d�veloppement maximal. Il faudra le stopper en �crivant \verb|{\z@#1}| � la ligne \no\aaa. On s'offre donc une macro qui effectue son travail en deux d�veloppements : le premier pour extraire son texte de remplacement et le deuxi�me qui lance celui de \idx\romannumeral.

\showcode/\catcode`\@11
\def\removefirstspaces{%��*\removefirstspaces�
       \romannumeral% lance le d�veloppement maximal�\idx*\romannumeral�
       \removefirstspaces@i% et passe la main � la macro r�cursive
}

\def\removefirstspaces@i#1{%
       \ifspacefirst{#1}% si #1 commence par un espace��*\ifspacefirst�
               {\exparg\removefirstspaces@i{\gobspace#1}}% recommencer sans le 1er espace��*\gobspace�*\exparg�
               {\z@#1}% sinon, renvoyer l'argument o� \z@ stoppe l'action de \romannumeral�\idx*\z@�
}
\catcode`\@12
\long\def\>#1<{"\detokenize{#1}"}�\idx*\long\idx*\detokenize�

a) \expandafter\expandafter\expandafter\>\removefirstspaces{12 {\bf3}4 567}<\qquad�\idx*\bf�*\removefirstspaces�
b) \expandafter\expandafter\expandafter\>\removefirstspaces{ 12 {\bf3}4 567}<\qquad
c) "\removefirstspaces{ 12 {\bf3}4 }"��*\removefirstspaces�/

\subsubsection{Supprimer les espaces de fin}
Programmons maintenant la macro �\removelastspaces\verb|{<texte>}| qui supprime les espaces qui se trouvent � la fin de son argument. Bien que l'algorithme soit un peu plus compliqu�, nous allons \emph{aussi} utiliser des arguments d�limit�s.

Pour d�crire la m�thode, prenons �\verb|W|� comme d�limiteur en supposant pour l'instant que cette lettre ne figure pas dans l'argument. L'id�e se d�compose en plusieurs �tapes :

\begin{enumerate}
       \item ajouter �\verb*|W W|� � la fin de l'argument;
       \item du r�sultat obtenu, prendre ce qui se trouve avant le premier �\verb*| W|�;
       \item ajouter �\verb|W|� � la fin du r�sultat obtenu;
       \item du r�sultat pr�c�dent, prendre ce qui se trouve avant le premier �\verb|W|�.
\end{enumerate}

�num�r� comme cela, il est quasi impossible de se repr�senter les diff�rentes �tapes et comprendre comment �volue l'argument. Aussi, nous allons prendre deux exemples pour d�crire les deux cas de figure pouvant se pr�senter, �\verb*|a|� qui ne finit pas par un espace et �\verb*|b |� qui se trouve dans le cas oppos� :

\begin{centrage}
\small
\begin{tabular}{clcc}
       \no d'�tape & decription & \verb*|a| & \verb*|b |\\\hline
       1& ajout de �\verb*|W W|� & \verb*|aW W|&\verb*|b W W|\\
       2& ce qui est avant �\verb*| W|� & \verb*|aW|&\verb*|b|\\
       3& ajout de �\verb*|W|� & \verb*|aWW|&\verb*|bW|\\
       4& ce qui est avant �\verb*|W|� & \verb*|a|&\verb*|b|\\\hline
\end{tabular}
\end{centrage}

Le cheminement est d�sormais plus clair et il est plus facile de se persuader que la m�thode fonctionne quels que soient �\verb|a|� et �\verb|b|�.

La m�thode pr�sente cependant un petit d�faut; elle indique ce qui se trouve \emph{avant} les d�limiteurs, mais ne dit pas un mot de ce qu'elle laisse \emph{apr�s}. Nous allons donc aussi r�colter les reliquats qui sont laiss�s apr�s les d�limiteurs.

Imaginons qu'au lieu de \verb*|W W|, nous ajoutions en fin d'argument �\verb*|W W\@nil|� lors de la premi�re �tape et que l'on fasse fonctionner les �tapes d�j� d�crites. Le fait nouveau sera qu'� la fin, on r�colte les reliquats se trouvant avant le \verb|\@nil|. \Qu'y trouverait-on ? Tout ce qui a �t� laiss� apr�s les d�limiteurs des lignes \no2 et 4. Le tableau est repris sauf qu'ici, les lignes grises montrent ce qui est laiss� apr�s ces d�limiteurs :

\begin{centrage}
\small
\begin{tabular}{clcc}
       \no d'�tape & description
& \verb*|a| & \verb*|b |\\\hline
       1& ajout de �\verb*|W W|� & \verb*|aW W|&\verb*|b W W|\\
       2& ce qui est avant �\verb*| W|� & \verb*|aW|&\verb*|b|\\
       \rowcolor{gray!40} & ce qui est apr�s �\verb*| W|� & \verb|<vide>|&\verb*| W|\\
       3& ajout de �\verb*|W|� & \verb*|aWW|&\verb*|bW|\\
       4& ce qui est avant �\verb*|W|� & \verb*|a|&\verb*|b|\\
       \rowcolor{gray!40} & ce qui est apr�s �\verb*|W|� & \verb*|W|&\verb|<vide>|\\\hline
\end{tabular}
\end{centrage}

Avant le \verb|\@nil| se trouve la concat�nation des reliquats partiels, c'est-�-dire :

\begin{itemize}
       \item �\verb|W|� dans le cas �\verb|a|�;
       \item �\verb*| W|� dans le cas �\verb*|b |�.
\end{itemize}

Il est int�ressant de remarquer que si le reliquat \emph{commence} par un espace, cela signifie que l'argument se finissait par un espace. Dans le cas pr�sent, puisque nous souhaitons supprimer \emph{tous} les espaces � la fin de l'argument, il va donc falloir mettre en place une r�cursivit� et recommencer dans le cas o� le reliquat commence par un espace.

R�glons enfin le d�limiteur �\verb|W|� qui nous a servi pour exposer la m�thode, mais qui ne peut �tre utilis� dans les vraies conditions, car trop probable dans un vrai argument. Rempla�ons-le par un caract�re bien plus improbable mais pas trop �exotique�, par exemple le caract�re de code 0 (qui s'�crit \verb|^^00|) et de catcode 12\footnote{Rien n'emp�cherait de lui assigner un catcode de 3 pour le rendre plus exotique.}\idx*{catcode!12 (autre)}.

\showcode/\catcode`\@11
\edef\catcodezero@saved{\number\catcode0 }% stocke le catcode de ^^00
\catcode0=12 % le modifie � 12
\def\removelastspaces#1{%
       \romannumeral% lance le d�veloppement maximal
       \removelastspaces@i\relax#1^^00 ^^00\@nil% mettre un \relax au d�but�\defline\aaa�
                                                % et passer la main � \removelastspaces@i
}
\def\removelastspaces@i#1 ^^00{% prendre ce qui est avant " W"
       \removelastspaces@ii#1^^00% ajouter "W"
}
\def\removelastspaces@ii#1^^00#2\@nil{% #1=ce qui est avant "W"  #2=reliquat
       \ifspacefirst{#2}% si le reliquat commence par un espace
               {\removelastspaces@i#1^^00 ^^00\@nil}% recommencer sans passer par \removelastspaces
               {\expandafter\z@\gobone#1}% sinon supprimer le \relax ajout� au d�but
                                         % et stopper l'action de \romannumeral avec \z@
}
\catcode0=\catcodezero@saved\relax% restaure le catcode de ^^00
\catcode`\@12
\long\def\>#1<{"\detokenize{#1}"}�\idx*\long\idx*\detokenize�

a) \expandafter\expandafter\expandafter\>\removelastspaces{ 12 {\bf3}4 }<\qquad
b) \expandafter\expandafter\expandafter\>\removelastspaces{12 {\bf3}4}<\qquad
c) "\removelastspaces{ 12 {\bf3}4 }"��*\removelastspaces�/

La premi�re remarque concerne le \idx\relax mis avant \verb|#1| tout au d�but afin d'�viter que \verb|#1| ne soit d�pouill� de ses accolades s'il s'agit d'un texte entre accolades. Ce \idx\relax est retir� juste avant que \idx\z@ ne stoppe l'action de \idx\romannumeral.

L'autre remarque, essentielle, est que l'appel r�cursif de la ligne \no\aaa{} n'appelle pas la macro chapeau �\removelastspaces. Cela �vite de lancer � chaque it�ration un nouveau \idx\romannumeral qui ne serait pas stopp� par la suite et provoquerait des erreurs de compilation.

\subsubsection{Supprimer les espaces extr�mes}
Tout est en place pour construire une macro �\removetrailspaces, charg�e de supprimer les espaces en trop se trouvant au d�but et � la fin de son argument. Il suffit d'assembler correctement les macros vues pr�c�demment. Cet assemblage m�rite une explication\ldots{} Si \verb|#1| est l'argument de cette macro, on voudrait pouvoir �crire

\centrecode-\removelastspaces{\removefirstspaces{<sp>#1<sp>}}-�*\removefirstspaces�*\removelastspaces

\noindent o� \verb|<sp>|  repr�sente d'�ventuels espaces extr�mes de \verb|#1|. Mais n'oublions pas que \TeX{} prend les arguments tels quels, sans les remplacer par ce qu'ils sont apr�s d�veloppement.

Pour que �\removefirstspaces\verb|{<sp>#1<sp>}| soit d�velopp�, nous allons d'abord lancer le d�veloppement maximal avec \idx\romannumeral en tout d�but de texte de remplacement de �\removetrailspaces. Comme pr�c�demment, cet artifice nous assurera que cette macro donne son r�sultat en deux d�veloppements.

Dans le code ci-dessus, convenons que �\textbullet� repr�sente un \idx\expandafter. Le pont d'\idx\expandafter, lui-m�me d�velopp� par \idx\romannumeral, va 2-d�velopper ��\removefirstspaces\verb|{<sp>#1<sp>}|� :

\begin{centrage}
       \small
       \idx\romannumeral\textbullet\textbullet\textbullet�\removelastspaces\textbullet\textbullet\textbullet\verb|{|�\removefirstspaces\verb|{<sp>#1<sp>}}|
\end{centrage}

\noindent Apr�s que les \idx\expandafter aient jou� leur r�le, la macro �\removefirstspaces a effectu� son travail et on obtient :

\centrecode-\removelastspaces{#1<sp>}-�*\removelastspaces

\noindent Enfin, comme \idx\romannumeral n'a toujours pas trouve de nombre, le d�veloppement se poursuit, la macro �\removelastspaces se 2-d�veloppe et nous obtenons :

\centrecode-#1-

Mais � ce stade, \idx\romannumeral est toujours en action et nous n'avons pas pens� � la stopper. Si \verb|#1| commence par un nombre au sens de \TeX{}, ce nombre sera captur� par \idx\romannumeral pour former les chiffres romains et sinon, \TeX{} se plaindra d'une erreur de compilation du type �\texttt{Missing number}�.

Pour r�gler ce probl�me, il faut revenir en arri�re et r�fl�chir o� mettre \idx\z@ pour qu'� la derni�re �tape ci-dessus, le \verb|#1| soit pr�c�d� de \idx\z@. Le bon endroit est juste avant �\removefirstspaces, mais surtout pas avant \verb|#1|, car ce \idx\z@ cacherait les �ventuels espaces au d�but de \verb|#1|. Remarquons au passage que ce token suppl�mentaire �\idx\z@� implique la prolongation du pont d'\idx\expandafter. Voici les �tapes du d�veloppement jusqu'au r�sultat final:

\begin{centrage}
       \small
       \idx\romannumeral\textbullet\textbullet\textbullet�\removelastspaces\textbullet\textbullet\textbullet\verb|{|\textbullet\textbullet\textbullet\verb|\z@|�\removefirstspaces\verb|{<sp>#1<sp>}}|\smallbreak
       �\removelastspaces\verb|{\z@#1<sp>}|\smallbreak
       \verb|\z@#1|\smallbreak
       \verb|#1|
\end{centrage}

Cette m�thode donne le code suivant :

\showcode/\catcode`\@11
\def\removetrailspaces#1{%��*\removetrailspaces�
       \romannumeral% lance le d�veloppement maximal�\idx*\romannumeral�
               \expandafter\expandafter\expandafter% le pont d'\expandafter
       \removelastspaces��*\removelastspaces�
               \expandafter\expandafter\expandafter% fait agir \removefirstspaces en premier
       {%
               \expandafter\expandafter\expandafter
       \z@% stoppe le d�veloppement initi� par \romannumeral�\idx*\z@�
       \removefirstspaces{#1}%��*\removefirstspaces�
       }%
}
\catcode`\@12
\long\def\>#1<{"\detokenize{#1}"}

a) \expandafter\expandafter\expandafter\>\removetrailspaces{ 12 {\bf3}4 }<\qquad�\idx*\bf�
b) \expandafter\expandafter\expandafter\>\removetrailspaces{12 {\bf3}4}<\par
c) \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter
  \foo\expandafter\expandafter\expandafter{\removetrailspaces{ 12 {\bf3}4 }}%
  signification : \meaning\foo.\par�\idx*\meaning�
c) ex�cution : "\foo"\par
d) "\removetrailspaces{ 12 {\bf3}4 }"��*\removetrailspaces�/

\subsubsection{La macro \texttt{\char`\\sanitizelist}}
Le plus dur est fait ! Nous allons maintenant pouvoir finir en douceur en �crivant la macro �\sanitizelist qui supprime tous les espaces extr�mes des �l�ments d'une liste. Le confort dont nous profitons ici est que �\removetrailspaces ne demande que deux d�veloppements pour donner son r�sultat.

Au fur et � mesure de la lecture de la liste, nous allons collecter dans la macro \verb|\item@list| les �l�ments purg�s de leurs espaces ind�sirables. Ici encore, nous placerons un \verb|\relax| avant chaque �l�ment (argument \verb|#1|), sous r�serve de le supprimer ensuite avec \verb|\gobone|. L'ajout de l'�l�ment en cours \verb|#1| au collecteur \verb|\item@list| se fera donc par :

\centrecode-\addtomacro\item@list{\removetrailspaces{\gobone#1},}-

\noindent sauf qu'il faut d�velopper les arguments avant que les macros ne s'en emparent. Ici, \verb|\gobone| doit �tre 1-d�velopp� en premier puis �\removetrailspaces doit �tre 2-d�velopp�. Cela va �tre le festival des \verb|\expandafter|, ou plut�t l'invasion ! Un \verb|\expandafter| est repr�sent� par $\bullet$ ci-dessous.

\begin{centrage}
\small
$\bullet\bullet\bullet\bullet\bullet\bullet\bullet$%
\verb|\addtomacro|%
$\bullet\bullet\bullet\bullet\bullet\bullet\bullet$%
\verb|\item@list|\par
$\bullet\bullet\bullet\bullet\bullet\bullet\bullet$%
\verb|{|$\bullet$\verb|\removetrailspaces|$\bullet$\verb|{\gobone#1},}|
\end{centrage}

\showcode/\catcode`\@11
\def\sanitizelist#1{% #1 = liste��*\sanitizelist�
       \let\item@list\empty% initialise le r�ceptacle de la liste assainie�\idx*\empty�
       \def\sanitizelist@endprocess{% d�finit le hook de fin�\idx*[ (m�thode de programmation)]{hook}�
               \expandafter\remove@lastcomma\item@list\@nil% supprimer derni�re virgule
               \let#1=\item@list% et assigner le r�sultat � #1
       }%
       \expandafter\sanitizelist@i\expandafter\relax#1,\quark@list,% aller � la macro r�cursive
}

\def\sanitizelist@i#1,{% #1="\relax" + �l�ment courant
       \expandafter\ifx\expandafter\quark@list\gobone#1%
       \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               {\sanitizelist@endprocess% si fin de liste, hook de fin�\idx*[ (m�thode de programmation)]{hook}�
               }% si la fin de la liste n'est pas atteinte :
               {\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter
                       \addtomacro% 1-d�velopper \gobone pour retirer \relax
               \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter
                       \item@list% puis 2-d�velopper \removetrailspaces
               \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter
                       {\expandafter\removetrailspaces\expandafter{\gobone#1},}% "#1"��*\removetrailspaces�
               \sanitizelist@i\relax% et continuer avec l'�l�ment suivant
               }%
}

\catcode`\@12
\frboxsep=0pt % encadrer au plus proche��*\frboxsep�
\def\foo#1{\frbox{\tt\strut#1} }% boite avec un strut et en fonte "tt" puis espace�\idx*\strut�*\frbox�
\def\liste{ Programmer, en \TeX{} ,est   ,{\bf facile}, et utile }
a) \runlist\liste\with\foo% encadrer les items��*\runlist�

b) \sanitizelist\liste% supprimer les espaces inutiles des items��*\sanitizelist�
  \runlist\liste\with\foo/\idx*[|)]{liste d'�l�ments}

Il est toujours possible d'�viter ces fastidieux ponts d'\verb|\expandafter|. Nous aurions pu mettre � contribution nos macros �\expsecond et �\eaddtomacro pour all�ger le code. Ces \verb|\expandafter| ont �t� laiss�s en l'�tat pour montrer que la gestion du d�veloppement est parfois assez p�nible.

\begin{centrage}
$\star$\par\nobreak
$\star$\quad$\star$
\end{centrage}

Apr�s avoir compris dans cette partie comment construire des macros r�cursives et donc, comment s'y prendre pour b�tir des boucles, nous allons poursuivre notre chemin.

Il s'agit d�sormais de lire non pas des arguments comme le font les macros, mais descendre � un niveau inf�rieur, celui des tokens. Pour prendre une analogie chimique, les arguments seraient les mol�cules tandis que les tokens seraient les atomes; l'un �tant fait avec l'autre. Il nous faut apprendre � programmer des macros qui lisent des tokens, un peu comme le fait \TeX{} lorsqu'il lit du code, mais en gardant la main apr�s chaque token de fa�on � �tre capable de \emph{contr�ler} chaque token lu et d'agir en cons�quence.
%|                                                                            |
%|                                Fin partie 3                                |
%|____________________________________________________________________________|

% ____________________________________________________________________________
%|                                                                            |
%|                                  Partie 4                                  |
%|                                                                            |
\defpartcomment{\lettrine[lines=3,nindent=0pt,slope=2pt]{\libertineInitialGlyph{M}}{\kern -2pt aintenant} que les arguments des macros n'ont plus de secrets, il faut apprendre � intervenir � un niveau plus bas, celui des tokens. En effet, pour certains besoins sp�cifiques, la lecture d'arguments par des macros est trop grossi�re et ne permet pas de les r�soudre de fa�on satisfaisante.}

\part{Au niveau des tokens}
\chapter{Mise en �vidence du probl�me}
Supposons que nous souhaitions effectuer un traitement sur chaque caract�re d'une phrase. Pour rendre les choses visuelles, choisissons d'encadrer chaque caract�re. L'id�e est de lire chaque caract�re de la phrase par une macro � argument puis d'encadrer ce caract�re � l'aide de la macro �\frbox vue dans la partie pr�c�dente. La r�cursivit� sera classique, une macro chapeau �\boxsentence se chargera de transmettre la phrase suivie d'un quark � une macro r�cursive. La macro r�cursive \verb|\boxsentence@i| lira donc un argument, le stockera dans une macro brouillon pour le comparer au \idx{quark} et tant que l'�galit� n'aura pas lieu, bouclera sur elle-m�me pour lire les arguments les uns apr�s les autres.

\showcode/\catcode`\@11
\def\boxsentence#1{%��*\boxsentence�
       \leavevmode% se mettre en mode horizontal�\idx*\leavevmode\idx*{mode!horizontal}�
       \boxsentence@i#1\quark% transmet "#1+\quark" � boxsentence@i��*\quark�
}
\def\boxsentence@i#1{% #1= argument lu
       \def\current@arg{#1}% stocke l'argument dans une macro temporaire
       \unless\ifx\quark\current@arg% si la fin n'est  pas atteinte�\tidx*{unless}�*\quark�
               \frbox{#1}% encadrer cet argument��*\frbox�
               \expandafter\boxsentence@i% lire l'argument suivant
       \fi
}
\catcode`@12
\frboxsep=1pt \frboxrule=0.2pt ��*\frboxsep�*\frboxrule�
\boxsentence{Programmer en \TeX\ est facile}��*\boxsentence�/

Les espaces sont ignor�s puisque la r�gle dit que lorsque les espaces ne sont pas envelopp�s entre accolades, ils sont ignor�s lorsque lus par une macro en tant qu'arguments. Si l'on avait voulu encadrer les espaces de cette phrase, il aurait fallu les �crire entre accolades ou bien utiliser la primitive \idx\ ou utiliser la macro \idx\space. Ce sont des artifices que l'on n'utilise jamais dans une phrase tap�e naturellement, sauf �ventuellement apr�s une s�quence de contr�le, comme ici apr�s \verb|\TeX|.
\grandsaut

Voici un autre exemple. On pourrait aussi vouloir �crire une macro et pouvoir l'appeler avec une \emph{variante}. Le moyen le plus commun�ment utilis� pour signifier que l'on souhaite la variante est d'�crire une �toile juste apr�s le nom de la macro. � charge pour la macro de tester si l'�toile est pr�sente ou pas et d'adopter deux comportements diff�rents selon le cas. En l'�tat actuel de nos connaissances, nous sommes oblig�s de lire l'argument qui suit afin de le tester pour d�terminer si cet argument est une �toile.

Appelons �\expo une macro sans argument qui, appel�e seule, produit l'exposant �${}^{\dag}$� et, appel�e �toil�e (\verb|\expo*|), affiche l'exposant �${}^{\ddag}$�\idx*{macro �toil�e}. Le signe �$\dag$� s'obtient avec la macro \idx\dag tandis que �$\ddag$� s'obtient avec \idx\ddag, ces macros devant op�rer en mode math�matique\idx*{mode!math�matique}.

Nous allons donc d�finir �\expo comme une macro admettant un argument :

\begin{itemize}
       \item si c'est une �toile, afficher �\verb|$^\dag$|�;
       \item si ce n'est pas une �toile, afficher �\verb|$^\ddag$|� et \emph{r��crire l'argument lu}.
\end{itemize}

\showcode|\catcode`\@11
\edef\star@macro{\string *}% stocke une �toile de catcode 12
\def\expo#1{%��*\expo�
       \def\temp@arg{#1}% stocke l'argument lu
       \ifx\star@macro\temp@arg\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               {% si l'argument est une �toile de catcode 12�\idx*{catcode!12\space(autre)}�
               $^\dag$% affiche une dague
               }% sinon
               {$^\ddag$% affiche une double dague
               {#1}% puis r�-�crit l'argument {#1}�\defline\aaa�
               }%
}
A\expo B\expo*C��*\expo�|

Bien que cela \emph{semble} fonctionner, on va tout droit � la catastrophe si on �crit :

\centrecode/A\expo \def\foo{BAR}/

\noindent En effet, � la ligne \no\aaa, en r��crivant l'argument \verb|#1|, \emph{on le met entre accolades}. Et donc ici, �\expo prendrait \verb|\def| comme argument. Ce \verb|\def| se retrouverait \emph{seul} entre accolades ce qui, lors de son ex�cution, d�clencherait une erreur du type �\texttt{Missing control sequence.}�. Rappelons-nous que \verb|\def| \emph{doit} �tre suivie d'une s�quence de contr�le ou d'un caract�re actif. On pourrait penser s'en sortir en r��crivant \verb|#1| � la ligne \no\aaa{}, c'est-�-dire sans entre accolades. Mais avec cette modification, si on �crit

\centrecode-A\expo {<code dans le groupe>}-

\noindent alors, le \verb|<code dans le groupe>| ne sera justement plus dans un groupe puisque d�pouill� des accolades par la macro �\expo lorsqu'elle le r��crit. Avec les cons�quences que l'on sait : toutes les assignations que l'utilisateur pensait confin�es dans le groupe seraient d�sormais de port�e globale !

Toute la difficult� vient du fait qu'une macro qui lit un argument ne \emph{peut pas savoir} si cet argument est envelopp� dans des accolades ou pas, notamment lorsque l'argument est un token unique. Ainsi, que l'on �crive �\verb|\foo A|� ou �\verb|\foo{A}|�, la macro \verb|\foo| lit dans les deux cas l'argument �\verb|A|� et ne peut pas d�terminer s'il �tait entre accolades ou pas.
\grandsaut

Pour r�sumer, la lecture d'arguments est d�fectueuse sur deux points essentiels :
\begin{itemize}
       \item les espaces ne sont pas vus comme des arguments et sont ignor�s (sauf si l'utilisateur les a d�lib�r�ment mis entre accolades);
       \item il est impossible pour une macro de faire la diff�rence entre l'argument �\verb|{x}|� et l'argument �\verb|x|� o� \verb|x| est un token quelconque (de catcode civilis� tout de m�me) autre qu'un espace.
\end{itemize}
\medbreak

Ces deux d�fauts rendent bien trop impr�cise la lecture d'un texte quelconque \emph{argument par argument} en vue d'effectuer une action pour chaque argument lu. Heureusement, on peut lire du code \emph{token par token}. Voyons comment\ldots

\chapter{Lire du code token par token}
Un petit rappel s'impose concernant la primitive \idx\let vue � partir de la page~\pageref{let}. Nous savons qu'elle agit au niveau des tokens. Sa syntaxe est la suivante :

\centrecode-\let\<macro>= <token>-

\noindent Et � la suite de cette assignation, la \verb|\<macro>| (qui peut �tre un caract�re actif) devient un alias pour le \verb|<token>|. Rappelons �galement que le test \verb|\ifx| se fait modulo la \idx\let-�galit�.

\section{Reprendre la main apr�s un \ttfamily \textbackslash let}
Comment construire une macro �\readtok qui lit le \verb|<token>| qui la suit et qui l'assigne avec \verb|\let| � \verb|\nxttok| ?

La chose n'a rien de compliqu�, il suffit de commencer l'assignation avec \idx\let � l'int�rieur du texte de remplacement de la macro pour que le \verb|<token>| soit lu � l'ext�rieur. Il est important d'�crire la syntaxe \emph{compl�te} de \idx\let dans le texte de remplacement, c'est-�-dire faire suivre \verb|\let\nxttok| de �\verb*|= |�. Si par exemple, le \verb|<token>| est �\verb|=|�, cette man\oe uvre nous assure que ce signe \verb|=| n'est pas compris comme faisant partie prenante de la syntaxe de \idx\let et soit perdu pour l'assignation. Voici comment on pourrait programmer la macro �\readtok :

\centrecodespc|\def\readtok{\let\nxttok= }|�*\readtok

En proc�dant de cette fa�on, m�me si la macro est suivie d'un signe �gal comme dans �\verb|\readtok=|�, ce signe �gal sera bien assign� � \verb|\nxttok|. Le probl�me est cependant �vident : la macro lit bien un \verb|<token>| et l'assigne � \verb|\nxttok|, mais \emph{c'est tout} ! Apr�s cette action, la macro s'ach�ve. Pour reprendre la main apr�s l'assignation afin d'appeler une autre macro \verb|\cmptok| charg�e d'analyser le \verb|<token>| lu, nous sommes bloqu�s. En effet, si nous voulons appeler une macro \verb|\cmptok| apr�s l'assignation, il serait absurde d'�crire

\centrecodespc-\def\readtok{\let\nxttok= \cmptok}-�*\readtok

\noindent car cela reviendrait � rendre \verb|\nxttok| �gal � \verb|\cmptok| et pour le coup, la macro �\readtok ne lirait rien du tout. On peut tourner le probl�me dans tous les sens, �\verb*|\let\nxttok= |� \emph{doit} se trouver � la toute fin du texte de remplacement de la macro.

\subsection{La primitive \texttt{\char`\\afterassignment}}\label{afterassignment}
Ce cas de figure a �t� pr�vu et la primitive \idx\afterassignment permet de s'en sortir.

\begin{regle}
La primitive \idx\afterassignment dont la syntaxe est

\centrecode-\afterassignment<token>-

stocke le \verb|<token>| dans un endroit sp�cial de la m�moire de \TeX{} pour le placer sur la \idx{pile d'entr�e} imm�diatement apr�s la prochaine assignation. Cette assignation peut r�sulter de l'utilisation de primitives d�j� vues \verb|\def|, \verb|\gdef|, \verb|\edef|, \verb|\xdef|, \idx\let, \idx\chardef, \idx\mathchardef, ou bien d'une assignation � un registre (de boite, d'entier, de ressort, de dimension, de token), voire apr�s une op�ration sur un registre d'entier ou de dimension par \idx\advance, \idx\multiply ou \idx\divide.

Si plusieurs \verb|\afterassignment<token>| sont rencontr�s avant une assignation, seul le dernier \verb|<token>| est pris en compte.

Lorsque \verb|\afterassignment<token>| est appel� avant \idx\setbox (c'est-�-dire avant l'assignation � un registre de boite), le \verb|<token>| est plac� en tout d�but de boite.
\end{regle}

Tout ceci nous conduit donc � programmer la macro �\readtok ainsi :

\centrecodespc-\def\readtok{\afterassignment\cmptok\let\nxttok= }-�*\readtok

D�s lors, on peut programmer une macro �\boxsentence qui va encadrer chaque token d'une phrase. Il suffira pour la macro \verb|\cmptok|, appel�e apr�s chaque assignation, d'encadrer le token lu (dont l'alias est \verb|\nxttok|) et de stopper la r�cursivit� si elle lit un token sp�cial (nous prendrons ici �\quark) que nous mettrons � la fin de l'argument de �\boxsentence.

\showcode/\def\boxsentence#1{%��*\boxsentence�
       \readtok#1\quark% met le token d'arr�t \quark � la fin de #1��*\quark�*\readtok�
}
\def\readtok{\afterassignment\cmptok\let\nxttok= }�\idx*\afterassignment�*\readtok�
\def\cmptok{%
       \unless\ifx\nxttok\quark% si la fin n'est pas atteinte�\tidx*{unless} �*\quark�
               \frbox{\nxttok}%  encadrer le token lu��*\frbox�
               \expandafter\readtok% puis aller lire le suivant��*\readtok�
       \fi
}
\frboxsep=1pt \frboxrule=0.2pt ��*\frboxsep �*\frboxrule�
\leavevmode\boxsentence{Programmer en \TeX\ est facile}�\idx*\leavevmode�*\boxsentence�/

Nous avons d�j� lev� un d�faut qui existait avec la lecture d'arguments : les espaces ne sont pas ignor�s lorsque lus apr�s \idx\let\verb|\<macro>|\verb*|= |.

\subsection{Application : retour sur la permutation circulaire des voyelles}
Reprenons l'exercice de la deuxi�me partie o� l'on effectuait une permutation circulaire sur les voyelles (voir page~\pageref{permutation.voyelles}). Appelons �\permutstart la macro qui marque le d�but de la zone o� cette permutation sera faite et �\permutend la macro qui marque la fin de cette zone.

Pour mener � bien cette permutation, il nous suffit de reprendre l'exemple pr�c�dent et tester dans \verb|\cmptok| si le token lu est successivement chacune des voyelles et dans chaque cas, afficher la voyelle suivante. La macro �\permutend sera un \idx{quark} :

\showcode/\def\permutstart{\afterassignment\cmptok\let\nxttok= }�\idx*\afterassignment�*\permutstart�
\def\permutend{\permutend}%��*\permutend�
\def\cmptok{%
       \unless\ifx\permutend\nxttok% tant que la fin n'est pas atteinte :�\tidx*{unless}�*\permutend�
               \ifxcase\nxttok��*\ifxcase�
               ae% si le token lu est "a", afficher un "e"
               ei io ou uy ya% etc pour les autres lettres
               \elseif��*\elseif�
                       \nxttok% si ce n'est aucune voyelle, afficher le token�\defline\aaa�
               \endif��*\endif�
               \expandafter\permutstart% aller lire le token suivant
       \fi
}
\permutstart Un "a" puis "e puis "i" ensuite, un "o", un "u" et "y".\permutend��*\permutend�*\permutstart�/

Cela semble fonctionner comme nous l'attendons, mais ce n'est qu'une impression. L'algorithme pr�sente un d�faut majeur : � la ligne \no\aaa, il met le token lu tel quel dans le flux de lecture de \TeX. Tout se passe bien tant qu'il ne s'agit que de tokens \emph{ind�pendants} et n'ayant aucun besoin les uns des autres. Si l'on avait �crit �\verb|\'e|�, le token �\idx\'� aurait �t� lu puis ex�cut� � la ligne \no\aaa. Comme ce token est une macro qui va lire l'argument suivant pour lui mettre un accent dessus, elle aurait donc captur� le premier \verb|\fi| de la ligne \no\number\numexpr\aaa+1{} avec deux cons�quences aussi graves l'une que l'autre :

\begin{itemize}
       \item ce \verb|\fi| captur� par \idx\' n'aurait pas �t� disponible pour le \verb|\ifx| appari� et donc, l'�quilibrage entre les \verb|\ifx| et les \verb|\fi| aurait �t� rompu en faveur des \verb|\ifx| qui auraient �t� exc�dentaires;
       \item l'argument de \idx\' ayant �t� \verb|\fi| au lieu d'une simple lettre comme elle l'attend. Il est quasi certain que cet argument aurait provoqu� une erreur de compilation puisque l'argument \verb|\fi| est un argument �explosif� d�s lors qu'il se retrouve dans un test (ce qui est le cas pour la macro \idx\' avec le \idx[!\LaTeX]{format} \LaTeX.).
\end{itemize}

Comme on l'a d�j� vu � l'exercice qui mettait les premi�res lettres de chaque mot en majuscule (lire page~\pageref{exo.majuscules}), il faudrait accumuler dans une variable les tokens au fur et � mesure de leur lecture. Il suffirait ensuite d'appeler cette variable en toute fin du processus. H�las, une fois que \verb|\nxttok| a �t� rendu \idx\let-�gal au token lu, on ne peut pas\footnote{On pourrait �ventuellement penser � \texttt{\string\meaning} mais les cas de figure � envisager sont tellement nombreux que cette man\oe uvre est irr�aliste.} savoir \emph{a posteriori} � quel token il a �t� rendu \idx\let-�gal. Certes, on peut le tester, le faire lire par \TeX{}  pour l'afficher, mais on ne peut pas savoir ce � quoi il est �gal ! L'affectation avec \idx\let est � sens unique\ldots{} C'est toute la diff�rence entre une \emph{macro} dont le texte de remplacement est facilement accessible (il suffit de la d�velopper) et entre une s�quence de contr�le assign�e avec \idx\let qui cache soigneusement ce � quoi elle est \idx\let-�gale. Impossible donc de faire comme avec une macro, de � d�velopper � la s�quence de contr�le \verb|\nxttok| pour l'ajouter � une variable qui collecterait les tokens lus. Il faudra attendre le chapitre suivant pour apprendre comment, avec l'aide d'une autre primitive, proc�der diff�remment.

\subsection{Lecture d'accolades explicites}
Essayons maintenant de corser la difficult� et de parcourir avec \idx\let du code qui contient des accolades explicites (c'est-�-dire des tokens de catcode 1\idx*{catcode!1 (accolade)} et 2). Faisons l'exp�rience avec le code vu au-dessus, o� chaque token est enferm� dans une boite encadr�e par la macro �\frbox programm�e dans la partie pr�c�dente :

\errcode/\def\boxsentence#1{\readtok#1\boxsentence}��*\boxsentence�*\readtok�
\def\readtok{\afterassignment\cmptok\let\nxttok= }
\def\cmptok{%
       %\show\nxttok% � d�commenter pour d�bogage
       \unless\ifx\nxttok\boxsentence
               \frbox{\nxttok}%��*\frbox�
               \expandafter\readtok
       \fi��*\readtok�
}
\frboxsep=1pt \frboxrule=0.2pt ��*\frboxsep �*\frboxrule�
\leavevmode\boxsentence{Pro{gra}mmer en \TeX\ est facile}�\idx*\leavevmode�*\boxsentence�/{! You can't use `\string\hrule' here except with leaders.}

Le message d'erreur n'est pas vraiment explicite, mais il est manifeste que quelque chose a mal tourn�. Pour avoir un d�but d'explication, on peut chercher � d�boguer ce code. Un simple �\idx\show\verb|\nxttok|� plac� tout au d�but de la macro \verb|\cmptok| �crira dans le \idx[!log]{fichier} \verb|log| ce qu'est \verb|\nxttok| � chaque it�ration. Voici ce que l'on obtient :% TODO : voir si un saut de page a lieu ici

\centrecode*|> \nxttok=the letter P.
> \nxttok=the letter r.
> \nxttok=the letter o.
> \nxttok=begin-group character {.
> \nxttok=the letter g.
> \nxttok=the letter r.
> \nxttok=the letter a.
> \nxttok=end-group character }.
! You can't use `\hrule' here except with leaders.
To put a horizontal rule in an hbox or an alignment,
you should use \leaders or \hrulefill (see The TeXbook).

! Missing number, treated as zero.
<to be read again>|

Les messages d'erreurs (qui commencent par �\verb|!|�) continuent sur plusieurs lignes, seuls les deux premiers ont �t� retranscrits ici.

Il est donc int�ressant de voir que \verb|\nxttok|, accolade ouvrante devenue \emph{implicite} (comme l'est \idx\bgroup) par le truchement de \idx\let, ne provoque pas d'erreur lorsqu'elle seule dans �\frbox. Ainsi donc, �\frbox\verb|{\bgroup}| est valide\ldots{} Mais ce n'est qu'apparent, car l'�quilibrage des accolades a �t� rompu et \TeX{} finirait t�t ou tard par se plaindre d'un �\texttt{Missing \} inserted}�. Avant qu'il puisse en arriver l�, l'erreur survient lorsque \idx\let enferme dans �\frbox l'accolade fermante explicite devenue implicite. Avant d'aller plus loin, il faut se souvenir que les boites de \TeX{} ont comme propri�t� que leurs accolades peuvent \emph{aussi} �tre implicites. � ce titre, les primitives de boites acceptent indiff�remment accolades explicites et implicites qui sont donc interchangeables. Pour expliquer l'erreur constat�e, voici la d�finition de �\frbox o� son argument \verb|#1| a �t� remplac� par un \idx\egroup � la ligne \no10 :

{\indencodenumtrue
\small
\indentcode-\def\frbox#1{%��*\frbox�
       \hbox{%
               \vrule width\frboxrule�\idx*\vrule�*\frboxrule�
               \vtop{%�\idx*\vtop�
                       \vbox{%�\idx*\vbox�
                               \hrule height\frboxrule�\idx*\hrule�
                               \kern\frboxsep�\idx*\kern�*\frboxsep�
                               \hbox{%�\idx*\hbox�
                                       \kern\frboxsep
                                       \egroup% est l'argument #1 de la macro�\idx*\egroup�
                                       \kern\frboxsep
                                       }%
                       }%
                       \kern\frboxsep�\idx*\kern�*\frboxsep�
                       \hrule height\frboxrule�\idx*\hrule�
               }%
               \vrule width\frboxrule�\idx*\vrule�*\frboxrule�
       }%
}-
}

Le \idx\egroup de la ligne \no10 ferme pr�matur�ment la \idx\hbox la plus int�rieure (ligne \no8), rejetant hors de celle-ci le \verb|\kern\frboxsep| de la ligne \no11. L'accolade explicite suivante (ligne \no12) ferme la \idx\vbox tandis que l'accolade explicite de la ligne \no13 ferme la \idx\vtop. Par cons�quent, \verb|\kern\frboxsep| et \idx\hrule (lignes \no14-15) se trouvent rejet�s hors de la \idx\vtop et prennent place dans la \idx\hbox chapeau de la ligne \no2, en mode horizontal interne\idx*{mode!horizontal interne} donc. C'est l� que la premi�re erreur survient car \idx\hrule ne peut �tre employ� en mode horizontal\idx*{mode!horizontal}, sauf justement � l'utiliser avec \idx\leaders comme le sugg�re le message d'erreur.

\grandsaut
Pour en revenir � la lecture d'un code avec \idx\let, on voit donc que les accolades explicites posent un vrai probl�me puisqu'elles sont derechef transform�es par \idx\let en leur � alias � \idx\bgroup ou \idx\egroup qui ne leur est pas �quivalent. L� encore, patientons jusqu'au chapitre suivant o� une nouvelle primitive nous permettra d'agir \emph{avant} que le token ne soit lu.

\subsection{Retour sur la macro \texttt{\char`\\litterate}}\idx*[|(]{verbatim}
Forts de nos connaissances, nous sommes en mesure d'�crire une variante �\Litterate de la macro �\litterate programm�e � la page~\pageref{litterate}. Son action �tait de d�sactiver tous les tokens sp�ciaux de fa�on � �crire exactement le texte situ� entre deux tokens identiques (par exemple �\verb-|-�) servant de d�limiteurs.

Le d�fi va �tre de fabriquer un �quivalent de la macro �\litterate mais sans modifier les catcodes. Pour y parvenir et pour rendre tous les tokens lus inoffensifs, il faudra faire en sorte que chaque token du texte lu soit pr�c�d� d'un \idx\string.

La premi�re chose � faire est de stocker le d�limiteur qui suit �\Litterate. Pour �tre surs que son catcode est 12,  nous allons le faire pr�c�der d'un \idx\string que nous d�velopperons : la s�quence de contr�le \verb|\lim@tok| recevra ce token. Par la suite, lorsque l'on parcourra le texte, si le token lu apr�s avoir �t� trait� par \idx\string est �gal � \verb|\lim@tok|, cela signifiera que le deuxi�me token d�limiteur est atteint et qu'il faut cesser la lecture.

\showcode/\catcode`\@11
\def\Litterate{%��*\Litterate�
       \begingroup% ouvrir un groupe
               \tt% et adopter une fonte � chasse fixe�\idx*\tt�
               \afterassignment\Litterate@i% apr�s l'assignation, aller � \Litterate@i�\idx*\afterassignment�
               \expandafter\let\expandafter\lim@tok\expandafter=\string% \lim@tok = token d�limiteur�\idx*\string�
}
\def\Litterate@i{%
               \afterassignment\Litterate@ii%apr�s avoir lu le prochain token, aller � \Litterate@ii�\idx*\afterassignment�
               \expandafter\let\expandafter\nxttok\expandafter=\string% lit le token suivant�\defline\aaa\idx*\string�
}
\def\Litterate@ii{%
       \ifx\nxttok\lim@tok% si le token suivant="token d�limiteur"
               \endgroup% fermer le groupe et finir
       \else
               \nxttok% sinon, afficher ce token�\defline\bbb�
               \expandafter\Litterate@i% et lire le token suivant
       \fi
}
\catcode`\@12
\Litterate|Programmer     en \TeX {} est << facile >> !|��*\Litterate�/

Cela ne fonctionne pas du tout comme on l'attendait :

\begin{itemize}
       \item les espaces sont ignor�s ;
       \item la s�quence de contr�le \idx\TeX est ex�cut�e.
\end{itemize}

En fait, les deux dysfonctionnements proviennent d'un m�me mal. L'erreur se trouve � la ligne \no\aaa{} de la macro \verb|\Litterate@i| qui lit le prochain token en d�veloppant au pr�alable \idx\string. Si cette macro s'appr�te � lire un espace, alors cet espace est pr�c�d� d'un \idx\string et donc, apr�s d�veloppement, cet espace reste inchang�. Il va �tre consid�r� par \TeX{} comme l'espace facultatif qui vient apr�s le signe �\verb|=|� dans la syntaxe de \idx\let ! Il sera donc ignor� et \verb|\nxttok| sera rendu \idx\let-�gal au token suivant, mais sans que ce token ne soit soumis � \idx\string puisque celui-ci a d�j� �t� utilis� par l'espace. Voil� pourquoi la macro \idx\TeX, qui se trouve juste apr�s un espace, n'est pas pass�e par \idx\string : \verb|\nxttok| est donc devenu un alias pour \idx\TeX et � la ligne \no\bbb, \verb|\nxttok| est ex�cut� et provoque l'affichage du logo de \TeX.

Pour corriger cette erreur de programmation, dans la macro \verb|\Litterate@i|, il \emph{faut} �crire l'espace apr�s le signe �\verb|=|� et sauter cet espace avec un \idx\expandafter de plus. Mais on ne peut pas �crire :

\centrecodespc|\expandafter\let\expandafter\nxttok\expandafter=\expandafter \string|

\noindent car l'espace serait ignor� puisque pr�c�d� par une s�quence de contr�le. Au lieu de cet espace \emph{explicite}, il va falloir �crire la macro \idx\space (dont le texte de remplacement est un espace) que nous allons 1-d�velopper apr�s avoir 1-d�velopp� \idx\string. Cela conduit � un pont d'\idx\expandafter.

\showcode/\catcode`\@11
\def\Litterate{%��*\Litterate�
       \begingroup% ouvrir un groupe
               \tt% et adopter une fonte � chasse fixe�\idx*\tt�
               \afterassignment\Litterate@i% apr�s l'assignation, aller � \Litterate@i�\idx*\afterassignment�
               \expandafter\let\expandafter\lim@tok\expandafter=\string% \lim@tok = token d�limiteur�\idx*\string�
}
\def\Litterate@i{%
       \afterassignment\Litterate@ii% apr�s avoir lu un token, aller � \Litterate@ii
               \expandafter\expandafter\expandafter% 1-d�velopper \string
       \let
               \expandafter\expandafter\expandafter% puis 1-d�velopper \space en " "
       \nxttok
               \expandafter\expandafter\expandafter
       =\expandafter\space\string% et lire le token obtenu�\idx*\space\idx*\string�
}
\def\Litterate@ii{%
       \ifx\nxttok\lim@tok% si le token suivant="token d�limiteur"
               \endgroup% fermer le groupe et finir
       \else
               \nxttok% sinon, afficher ce token�\defline\bbb�
               \expandafter\Litterate@i% et lire le token suivant
       \fi
}
\catcode`\@12
\Litterate|Programmer     en \TeX {} est << facile >> : $~$^_#|��*\Litterate�/

Derni�re observation : le r�sultat n'est pas \emph{exactement} ce qui est entre les d�limiteurs. Deux r�gles de lecture du code s'appliquent toujours :
\begin{itemize}
       \item plusieurs espaces cons�cutifs sont lus comme un seul;
       \item un espace qui suit une s�quence de contr�le est ignor�. Ici, l'espace qui suit la macro \idx\TeX est ignor�.
\end{itemize}

Ces deux r�gles concernent les espaces, c'est-�-dire les tokens de catcode 10\idx*{catcode!10 (espace)}. Pour les contourner, nous allons devoir l�g�rement enfreindre la contrainte que nous nous �tions donn�e : changer le catcode de l'espace � 12 pour que les r�gles ne s'appliquent plus. Il suffit donc d'�crire

\centrecodespc|\catcode`\ =12 |

\noindent juste apr�s le \idx\begingroup pour que les espaces soient tous affich�s.

La conclusion est que �\Litterate fonctionne bien, mais de par l'assignation et le test qu'elle effectue pour chaque token, elle est \emph{beaucoup plus lente} que son homologue �\litterate. Cette derni�re ne s'encombrait pas de tant pr�cautions. Une fois les catcodes chang�s et les \idx{ligature}s d�sactiv�es, elle laissait \TeX{} librement lire le texte jusqu'� ce qu'il rencontre le d�limiteur de fin qui, rendu actif et \idx\let-�gal � \idx\endgroup, redonnait aux tokens sp�ciaux leur catcode normal et mettait fin au comportement initi� par �\litterate\idx*[|)]{verbatim}.

\begin{exercice}
Cr�er une macro �\letterspace de syntaxe

\centrecode-\letterspace{<dimension de ressort>}{<texte>}-

o� le \verb|<texte>| est constitu� de tokens de catcode 10, 11 ou 12. L'action de cette macro est d'afficher entre chaque caract�re du \verb|<texte>| un ressort dont la dimension est sp�cifi�e dans le premier argument.

\solution
Puisque l'on sait lire un argument token par token, on va largement s'inspirer de ce qui a �t� fait avec la macro �\Litterate.

\showcode/\catcode`@11
\newskip\ltr@spc�\idx*\newskip�
\def\letterspace#1#2{%��*\letterspace�
       \ltr@spc=#1\relax % assigne le ressort
       \letterspace@i#2\letterspace@i% appelle la macro \letterspace@i
}
\def\letterspace@i{%
       \afterassignment\letterspace@ii�\idx*\afterassignment�
       \let\nxttok=
}
\def\letterspace@ii{%
       \ifx\nxttok\letterspace@i% si la fin est atteinte
               \unskip% supprimer le dernier ressort qui est de trop�\idx*\unskip�
       \else
               \nxttok% afficher le token
               \hskip\ltr@spc\relax% ins�re le ressort�\idx*\hskip�
               \expandafter\letterspace@i% va lire le token suivant
       \fi
}
\catcode`@12
Voici "\letterspace{0.3em}{des lettres espac�es}"
et voici "\letterspace{-0.075em}{de la compression}".��*\letterspace�/

Mais attention, si cela fonctionne ici, c'est parce que l'\idx{encodage} du code source de ce livre est \latin et donc, le caract�re �\verb|�|� est vu comme un seul token. Si l'\idx{encodage} avait �t� \utf et le moteur 8 bits, le caract�re �\verb|�|�, cod� sur 2 \idx{octet}s, aurait �t� vu comme \emph{deux} tokens. Ceux-ci sont ins�parables pour former la lettre \verb|�| (le premier est actif et prend le second comme argument). Comme l'algorithme les aurait s�par�s, on aurait certainement eu une erreur de compilation. Le m�me probl�me serait apparu si l'on avait �crit �\idx\'\verb|e|�.
\end{exercice}

\begin{exercice}
Inventer un proc�d� qui permet � une macro �\ifinteger de tester si son argument est un nombre entier. La syntaxe sera :
\centrecode-\ifinterger{<caract�res>}{<vrai>}{<faux>}-

\solution
L'id�e directrice est de d�finir un compteur, de faire pr�c�der l'argument de cette macro d'un �\verb|0|� et d'assigner \verb|0#1| au compteur :

\centrecode-<compteur>=0#1\relax-

Le �\verb|0|� nous assure qu'au moins un caract�re servira � former un \verb|<nombre>|. Apr�s cette assignation, il faut aller voir ce qu'il reste jusqu'au \verb|\relax| et qui ne sert pas � la formation du \verb|<nombre>|. S'il ne reste rien, alors la totalit� de l'argument �tait constitu�e de caract�res pouvant entrer dans la composition d'un \verb|<nombre>| et peut donc �tre assimil�e � un entier.

On va rencontrer un petit grain de sable lorsque \verb|#1| commence par le caract�re �\verb|-|� car

\centrecode|0-<caract�res>|

\noindent sera compris comme le nombre \verb|0| suivi d'autres tokens ne pouvant entrer dans la composition d'un nombre � cause du �\verb|-|�. Il faut donc pr�voir de tester si \verb|#1| commence par �\verb|-|� � l'aide de la macro �\ifstart vue � la page~\pageref{ifstart} de la troisi�me partie. Si le test est positif, on se contentera de manger ce signe �\verb|-|� et recommencer avec ce qui reste dans \verb|#1|. Pour �viter qu'un argument vide donne un test �\ifinteger positif, il est pr�f�rable de tester si \verb|#1| est vide auquel cas il faut lire l'argument \verb|<faux>|.

\showcode|\catcode`@11
\newcount\test@cnt�\idx*\newcount�
\def\ifinteger#1{%��*\ifinteger�
       \ifstart{#1}{-}% si "-" est au d�but de #1��*\ifstart�
               {\exparg\ifinteger{\gobone#1}% l'enlever et recommencer��*\ifinteger�*\exparg�
               }
               {\ifempty{#1}% sinon, si #1 est vide��*\ifempty�
                       \secondoftwo% lire l'argument <faux>
                       {\afterassignment\after@number% sinon, apr�s l'assignation, aller � \after@number�\idx*\afterassignment�
                       \test@cnt=0#1\relax% faire l'assignation
                                          %(\relax termine le nombre et n'est pas mang�)
                       }%
               }%
}
\def\after@number#1\relax{% #1 est ce qui reste apr�s l'assignation
       \ifempty{#1}% teste si #1 est vide et lit l'argument <vrai> ou <faux> qui suit��*\ifempty�
}

\catcode`@12
1) \ifinteger{5644}{oui}{non}\qquad
2) \ifinteger{-987}{oui}{non}\qquad
3) \ifinteger{6a87}{oui}{non}\qquad
4) \ifinteger{abcd}{oui}{non}\qquad
5) \ifinteger{-a}{oui}{non}\qquad
6) \ifinteger{-}{oui}{non}\qquad
7) \ifinteger{3.14}{oui}{non}��*\ifinteger�|

Ajoutons que la macro �\ifinteger n'est pas d�veloppable, car elle contient trois choses qui ne le sont pas :
\begin{enumerate}
       \item la macro �\ifstart;
       \item l'assignation � un compteur;
       \item la primitive \idx\afterassignment.
\end{enumerate}
\end{exercice}

\subsection{En r�sum�...}
Prenons le temps de faire le point sur la lecture token par token. Du c�t� des avantages :

\begin{itemize}
       \item les espaces sont bien lus ;
       \item il est possible de faire un test sur chaque token apr�s qu'il ait �t� lu.
\end{itemize}

Et du c�t� des d�fauts:

\begin{itemize}
       \item lorsqu'un token a �t� lu et assign� � une s�quence de contr�le par \idx\let, on ne peut plus savoir quel �tait le token lu. Par cons�quent, il est impossible d'ajouter ce token � une variable cumulative que l'on pourrait d�velopper � la fin, hors de toute r�cursivit�. Si l'on veut afficher le token lu, on doit mettre la s�quence de contr�le qui lui est \idx\let-�gale dans le flux de lecture pendant la boucle r�cursive ce qui, on l'a vu, peut entrainer des probl�mes lorsque des tokens sont des macros n�cessitant un ou plusieurs arguments ;
       \item les tokens de catcode 1\idx*{catcode!1 (accolade)} et 2 (�\verb|{|� et �\verb|}|�) sont d�natur�s par une assignation via \idx\let et deviennent \idx\bgroup et \idx\egroup.
\end{itemize}

La conclusion est sans appel : la lecture token par token souffre de d�fauts qui la rendent bien peu commode. La suite va certainement adoucir cette conclusion\ldots{}

\section{Lire un token sans avancer la t�te de lecture}
Le titre ci-dessus a de quoi surprendre puisqu'on a consid�r� jusqu'� pr�sent que toute lecture entrainait l'in�vitable avanc�e de la t�te de lecture de \TeX{} ! Il y a eu l� un petit mensonge par omission puisqu'il y a une seule exception � cette r�gle.

\begin{regle}
La primitive \idx\futurelet a la syntaxe suivante :

\centrecode-\futurelet\<macro><token1><token2>-

L'effet est le suivant :

\begin{enumerate}
       \item \TeX{} effectue l'action �\verb*|\let\<macro>= <token2>|� (en figeant le catcode de \verb|<token2>|);
       \item puis la t�te de lecture avance jusqu'� \verb|<token 1><token2>| qui restent intacts, comme s'ils n'avaient pas �t� lus.
\end{enumerate}

Il y a comme un air de ressemblance avec \idx\expandafter sauf qu'il n'est pas question de d�veloppement, mais d'assignation via \idx\let : il y a bien le �saut� de \verb|<token1>| pour faire une assignation sans que la t�te de lecture ne bouge. Tout se passe comme si \TeX{} allait lire le \verb|<token2>| pour le \emph{copier} juste apr�s \verb|\<macro>| pour effectuer une assignation avec un \idx\let. Et donc, le code

\centrecode-\futurelet\<macro><token1><token2>-\idx*\futurelet

\noindent est �quivalent �

\centrecode-\let\<macro>= <token2><token1><token2>-
\end{regle}

Assur�ment, \idx\futurelet est une primitive formidable car elle va r�gler tous nos probl�mes. En effet, si le texte de remplacement d'une \verb|\<macro>| se termine par

\centrecode-\futurelet\nxttok\testtok-\idx*\futurelet

\noindent alors, le token se trouvant juste apr�s cette \verb|\<macro>| sera lu et stock� dans \verb|\nxttok|, mais la t�te de lecture n'aura pas boug� et ce token qui se trouve hors de la macro restera intact\footnote{En particulier, les accolades explicites restent explicites et ne sont pas transform�es en leurs alias \texttt{\string\bgroup} ou \texttt{\string\egroup}.}. Il suffira que la macro \verb|\testtok| teste ce token pour d�cider l'action � faire. Cette primitive permet donc de pr�voir (d'un token) le futur, c'est sans doute pourquoi elle s'appelle \idx\futurelet et non pas \verb|\letafter|.
\grandsaut

Voici comment programmer une macro �\teststar dont le comportement va changer selon qu'elle est imm�diatement suivie d'une �toile ou non : la version \emph{normale} composera l'argument en italique et la version \emph{�toil�e}\idx*{macro �toil�e} en gras. Clairement, un \idx\futurelet sera utilis� pour savoir si le token qui suit imm�diatement �\teststar est une �toile; la macro qui sera charg�e de tester ce token est \verb|\teststar@i| :

\showcode|\catcode`\@11
\def\teststar{%��*\teststar�
       \futurelet\nxttok\teststar@i% % pioche le token suivant puis aller � \teststar@i�\idx*\futurelet�
}
\def\teststar@i{%
       \ifx *\nxttok\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               {% si le token suivant est une �toile
               \afterassignment\teststar@bf% apr�s avoir lu "*", aller � \teststar@bf�\idx*\afterassignment�
               \let\nxttok= % lire l'�toile
               }% si le token n'est pas une �toile
               {\teststar@it% aller � \teststar@it
               }%
}
\def\teststar@bf#1{{\bf#1}}% lit l'argument et le compose en gras dans un groupe�\idx*\bf�
\def\teststar@it#1{{\it#1\/}}% lit l'argument et le compose en italique�\idx*\it\idx*[ (correction d'italique)]\/�
\catcode`\@12
Un essai \teststar{r�ussi} et un essai \teststar*{�toil�} r�ussi aussi.��*\teststar�|

Il serait plus int�ressant de programmer une macro � caract�re g�n�raliste ��\ifnexttok� dont la syntaxe serait :

\centrecode-\ifnexttok<token>{<code vrai>}{<code faux>}-

\noindent que l'on placerait � la fin du texte de remplacement d'une macro et qui irait tester le prochain token ext�rieur � la macro non �gal � un espace. Le \verb|<code vrai>| serait ex�cut� s'il est �gal � \verb|<token>| et \verb|<code faux>| sinon.

Pour savoir si le token lu est un espace, nous le comparerons � �\sptoken d�fini � la page~\pageref{sptoken}. Profitons-en pour d�couvrir une autre fa�on (parmi beaucoup d'autres) de d�finir �\sptoken avec une macro �\deftok :

\showcode|\catcode`@11
\def\deftok#1#2{\let#1= #2\empty}% d�finit le token #1 (\empty au cas o� #2 est vide)��*\deftok�
\deftok\sptoken{ }��*\sptoken�
\def\ifnexttok#1#2#3{% lit les 3 arguments : #1=token #2=code vrai #3=code faux��*\ifnexttok�
       \deftok\test@tok{#1}% stocke le token cherch餧*\deftok�
       \def\true@code{#2}\def\false@code{#3}% et les codes � ex�cuter
       \ifnexttok@i% aller � la macro r�cursive
}
\def\ifnexttok@i{%
       \futurelet\nxttok\ifnexttok@ii% piocher le token d'apr�s et aller � \ifnexttok@ii�\idx*\futurelet�
}
\def\ifnexttok@ii{%
       \ifx\nxttok\sptoken% si le prochain token est un espace��*\sptoken�
               \def\donext{%
                       \afterassignment\ifnexttok@i% recommencer apr�s�\idx*\afterassignment�
                       \let\nxttok= % apr�s avoir absorb� cet espace
               }%
       \else
               \ifx\nxttok\test@tok% si le prochain token est celui cherch�
                       \let\donext\true@code% ex�cuter le code vrai
               \else
                       \let\donext\false@code% sinon code faux
               \fi
       \fi
       \donext% faire l'action d�cid�e ci-dessus
}
\catcode`@12
\ifnexttok W{je vais lire un W : }{je ne vais pas lire un W : }W.\par
\ifnexttok W{je vais lire un W : }{je ne vais pas lire un W : }a.\par
\ifnexttok *{je vais lire une �toile : }{je ne vais pas lire une �toile : } *.\par
\ifnexttok *{je vais lire une �toile : }{je ne vais pas lire une �toile : }a.��*\ifnexttok�|

Cela fonctionne bien comme on l'attend notamment � l'avant-derni�re ligne o� l'�toile est s�par�e de l'accolade fermante par un espace. Le test est pourtant positif ce qui montre que les espaces sont bien ignor�s.

\begin{exercice}
Comment pourrait-on modifier la macro �\ifnexttok pour lui donner une option afin de choisir d'ignorer les espaces ou pas ?
\solution
Le plus simple est de d�finir un bool�en \verb|\iftestspace| que l'on mettrait � faux par d�faut et � vrai si l'on se trouve dans des conditions o� l'on veut prendre en compte les espaces.

\showcode|\catcode`@11
\newif\iftestspace \testspacefalse�\idx*\newif�
\def\deftok#1#2{\let#1= #2}\deftok\sptoken{ }��*\deftok �*\sptoken�
\def\ifnexttok#1#2#3{% #1=token #2=code vrai #3=code faux��*\ifnexttok�
       \let\test@tok= #1% stocke le token � tester
       \def\true@code{#2}\def\false@code{#3}% et les codes � ex�cuter
       \iftestspace \def\ifnexttok@i{\futurelet\nxttok\ifnexttok@ii}%�\idx*\futurelet�
       \else        \def\ifnexttok@i{\futurelet\nxttok\ifnexttok@iii}%�\idx*\futurelet�
       \fi% apr�s avoir d�fini la macro r�cursive selon le bool�en,
       \ifnexttok@i% l'ex�cuter
}
\def\ifnexttok@ii{% macro "normale" qui ne teste pas les espaces
       \ifx\nxttok\test@tok \expandafter\true@code% ex�cuter le code vrai
       \else                \expandafter\false@code% sinon code faux
       \fi
}
\def\ifnexttok@iii{% macro qui ignore les espaces
       \ifx\nxttok\sptoken% si le prochain token est un espace��*\sptoken�
               \def\donext{%
                       \afterassignment\ifnexttok@i% lire le token d'apr�s�\idx*\afterassignment�
                       \let\nxttok= % apr�s avoir absorb� l'espace
               }%
       \else
               \let\donext\ifnexttok@ii% sinon, faire le test "normal"
       \fi
       \donext% faire l'action d�cid�e ci-dessus
}
\catcode`@12
\testspacefalse
\ifnexttok W{je vais lire un W : }{je ne vais pas lire un W : }W.\par
\ifnexttok W{je vais lire un W : }{je ne vais pas lire un W : } W.\medbreak
\testspacetrue
\ifnexttok W{je vais lire un W : }{je ne vais pas lire un W : }W.\par
\ifnexttok W{je vais lire un W : }{je ne vais pas lire un W : } W.��*\ifnexttok�|
\end{exercice}

�laborons � pr�sent une macro �\ifstarred qui permettrait de tester, lorsque plac�e � la fin du texte de remplacement d'une macro, si cette derni�re est �toil�e ou pas et agir en cons�quence\idx*{macro �toil�e}. La syntaxe serait :

\centrecode-\ifstarred{<code vrai>}{<code faux>}-

Gardons en m�moire qu'en cas de test positif avec �\ifnexttok, l'�toile n'est pas mang�e. Il faut donc trouver un moyen de manger cette �toile et le plus simple est d'utiliser \verb|\firstoftwo| o� le premier argument sera \verb|<code vrai>| et le second l'�toile, non encore lue.

\centrecode/\def\ifstarred#1#2{% #1=code vrai  #2=code faux��*\ifstarred�
       \ifnexttok *% si le prochain token est une �toile��*\ifnexttok�
               {\firstoftwo{#1}}% le 2e argument de \firstoftwo est "*"
               {#2}% sinon, ex�cuter le code faux
}/

Comme l'argument \verb|{#2}| figure une seule fois dans la macro en derni�re position, nous pouvons nous permettre de ne pas l'�crire dans le texte de remplacement de �\ifstarred. Au risque d'�tre bien moins compr�hensible, le code peut donc se simplifier en :

\centrecode-\def\ifstarred#1{\ifnexttok*{\firstoftwo{#1}}}-

\showcode|\def\ifstarred#1{\ifnexttok*{\firstoftwo{#1}}}��*\ifstarred�*\ifnexttok�
\catcode`\@11
\def\teststar{\ifstarred{\teststar@bf}{\teststar@it}}��*\ifstarred�*\teststar�
\def\teststar@bf#1{{\bf#1}}�\idx*\bf�
\def\teststar@it#1{{\it#1\/}}�\idx*\it\idx*[ (correction d'italique)]\/�
\catcode`\@12

Un essai \teststar{r�ussi} et un essai \teststar*{�toil�} r�ussi aussi.��*\teststar�|

\section{Parser du code}\label{parser.code}\idx*[|(]{parser du code}
\subsection{La macro \texttt{\char`\\parse}}�*\parse[|(]
L'utilisation conjointe de \idx\futurelet et de la lecture d'arguments est la m�thode qu'il nous faut pour parcourir et analyser du code (l'anglicisme \emph{parser du code} est souvent employ�). Inventons une syntaxe simple :�*\parse

\centrecode-\parse<code � parser>\parsestop-�*\parsestop

\noindent Le bond en avant que permet \idx\futurelet est de savoir, avant de l'avoir absorb�, si le token qui suit dans le code est un token � � probl�me � comme le sont l'espace et l'accolade ouvrante. Le principe va �tre de parcourir le code et selon ce que l'on rencontre, ajouter des tokens au fur et � mesure dans un collecteur (qui sera un registre de tokens \verb|\code@toks|).

Nous allons nous fixer comme objectif que si le \verb|<code � parser>| contient un texte entre accolades, celui-ci sera ajout� tel quel au collecteur. En revanche, pour les autres tokens y compris l'espace, un test sera fait et selon le token rencontr�, on pourra choisir ce que l'on ajoute au collecteur. Cela implique qu'un test sera effectu� � chaque it�ration sur le prochain token non encore absorb�.

Voici l'algorithme qui va parser le code :

\begin{algo}
       \item initialiser \verb|\code@toks| � vide;
       \item lire le prochain token \verb|\nxttok| avec \idx\futurelet.
       \item si \verb|\nxttok| est �\parsestop, manger �\parsestop et afficher le collecteur \verb|\code@toks|;
       \item si \verb|\nxttok| est diff�rent de �\parsestop
       \begin{algo}
               \item si \verb|\nxttok| est un espace, manger l'espace et aller en 5 en transmettant �\verb*| |� ;
               \item si \verb|\nxttok| est une accolade ouvrante (qui est vue comme un \idx\bgroup par \idx\futurelet), lire l'argument form� par le texte entre accolades et l'ajouter � \verb|\code@toks| puis retourner en 2;
               \item dans les autres cas, aller en 5 pour lire ce prochain token;
       \end{algo}
       \item tester le token transmis en argument et, selon l'issue du test, ajouter ce que l'on souhaite � \verb|\code@toks| puis, retourner en 2.
\end{algo}

Du point de vue des macros � �crire, le point \no1 est effectu� par la macro chapeau �\parse, le point \no2 sera l'affaire d'une macro auxiliaire \verb|\parse@i| et les points \nos3 et 4 seront effectu�s par la macro \verb|\parse@ii|. Le point \no5 sera une macro \emph{publique} ��\testtoken� � un argument, �crite par l'utilisateur pour y effectuer les tests qu'il souhaite sur l'argument et selon l'issue de ceux-ci, ajouter ce qu'il souhaite au collecteur de tokens.

\label{parse}\showcode|\catcode`\@11
\def\parsestop{\parsestop}% d�finit la macro-quark se trouvant en fin de code��*\parsestop�
\newtoks\code@toks% registre contenant le code lu�\idx*\newtoks�
\def\parseadd{\addtotoks\code@toks}��*\addtotoks�
\def\parse{%��*\parse�
       \code@toks={}% initialise \code@toks � vide
       \parse@i% et passe la main � \parse@i
}
\def\parse@i{\futurelet\nxttok\parse@ii}% lit le prochain token et va � \parse@ii�\idx*\futurelet�
\def\parse@ii{%
       \ifxcase\nxttok��*\ifxcase�
               \parsestop\parsestop@i% si la fin va �tre atteinte, aller � \parsestop@i��*\parsestop�
               \sptoken\read@space% si un espace va �tre lu, aller � \read@space��*\sptoken�
               \bgroup\read@bracearg% si une accolade ouvrante  aller � \read@bracearg�\idx*\bgroup�
       \elseif��*\elseif�
               \testtoken% dans les autres cas, aller � \testtoken��*\testtoken�
       \endif��*\endif�
}

\def\parsestop@i\parsestop{% la fin est atteinte : manger \parsestop
       \the\code@toks% afficher le registre de tokens�\idx*\the�
}
\expandafter\def\expandafter\read@space\space{% manger un espace dans le code�\idx*\space�
       \testtoken{ }% et aller � \testtoken��*\testtoken�
}
\def\read@bracearg#1{% l'argument entre accolades est lu
       \parseadd{{#1}}% puis ajout� (entre accolades) tel quel � \code@toks
       \parse@i% ensuite, lire le prochain token
}
\catcode`@12

{\bf Exemple 1 :}
\catcode`@11
\def\testtoken#1{% macro qui teste le token��*\testtoken�
       \ifxcase{#1}��*\ifxcase�
               a{\parseadd{e}}% remplacer a par e
               e{\parseadd{i}}% e par i
               i{\parseadd{o}}% i par o
               o{\parseadd{u}}% o par u
               u{\parseadd{y}}% u par y
               y{\parseadd{a}}% y par a
       \elseif��*\elseif�
               \parseadd{#1}% sinon, ajouter le token tel quel
       \endif��*\endif�
       \parse@i% aller lire le token suivant
}%
\catcode`@12
\parse
Ce texte devenu \`a peine reconnaissable montre que le r\'esultat contient des sonorit\'es
{\bf catalanes, corses ou grecques} assez inattendues.�\defline\aaa\idx*\bf�
\parsestop\medbreak�\idx*\medbreak�*\parsestop�

{\bf Exemple 2 :}�\idx*\bf�
\leavevmode \frboxsep=1pt �\idx*\leavevmode�*\frboxsep�
\catcode`@11
\def\testtoken#1{%��*\testtoken�
       \ifxcase{#1}% si #1 est un espace��*\ifxcase�
               { }{\parseadd{\hskip 0.75em }}% ajouter un espace
               \ {\parseadd{\hskip 0.75em }}
       \elseif��*\elseif�
               \parseadd{\frbox{#1}}% sinon, l'encadrer��*\frbox�
       \endif��*\endif�
       \parse@i}%
\catcode`@12
\parse Programmer en \TeX\ est facile\parsestop\medbreak�\idx*\medbreak�*\parsestop�

{\bf Exemple 3 :}
\catcode`@11
\def\testtoken#1{%��*\testtoken�
       \ifx a#1\parseadd{X}\else\parseadd{#1}\fi% remplace les "a" par des "X"
       \parse@i
}
\catcode`@12
\parse a\bgroup\bf braca\egroup dabra\parsestop��*\parse\idx*\bgroup\idx*\egroup�*\parsestop�|

On le voit, le code entre accolades (ligne \no\aaa) n'a pas �t� modifi�, c'est ce que l'on s'�tait fix� dans le cahier des charges.

\begin{exercice}
Une zone d'ombre subsiste quant � la s�quence de contr�le \idx\bgroup. En effet, une accolade ouvrante explicite sera vue par \idx\futurelet comme \idx\bgroup. Par cons�quent, la macro �\parse \emph{ne sait pas distinguer} une accolade ouvrante de la s�quence de contr�le \idx\bgroup.

\begin{enumerate}
       \item D�crire ce que contient le registre de tokens \verb|\code@toks| lors de l'exemple \no3.
       \item \Qu elle difficult� se pr�sente si on souhaite parser �\verb|\hbox\bgroup XY\egroup|� ?
       \item Comment peut-on r�soudre cette difficult� ?
\end{enumerate}
\solution
Lorsque le token qui doit �tre lu est \idx\bgroup, la fa�on dont est programm�e \verb|\parse@ii| lui fait croire � tort que ce qui suit est une accolade ouvrante. La macro \verb|\read@bracearg| lit donc l'argument (qui est ici \idx\bgroup) et le met entre accolades. Le registre de tokens contient donc

\centrecode-X{\bgroup}\bf brXcX\egroup dXbrX-
\grandsaut

Pour la question \no2, la r�ponse est donn�e � la question pr�c�dente. En effet, si l'on parse

\centrecode|\hbox\bgroup XY\egroup|

le registre de tokens va contenir

\centrecode|\hbox{\bgroup}XY\egroup|

La \idx\hbox va donc contenir un simple \idx\bgroup au lieu du \verb|XY|.
\grandsaut

R�pondre � la question \no3 est difficile. Pour r�soudre le probl�me, nous allons tout d'abord construire une macro �\ifbracefirst de syntaxe

\centrecode-\ifbracefirst{<argument>}{<code vrai>}{<code faux>}-�*\ifbracefirst

\noindent qui ex�cute \verb|<code vrai>| si son \verb|<argument>| commence par une accolade ouvrante (ou tout autre token de catcode 1) et \verb|<code faux>| sinon.

Le simple fait que �\ifbracefirst admette un argument et non un token implique de renoncer � la lecture \emph{au fur et � mesure} du \verb|<texte>| entre �\parse et �\parsestop. Nous sommes contraints de lire la \emph{totalit�} de ce qui reste avant �\parsestop et de transmettre cet \verb|<argument>| � �\ifbracefirst.

Pour mener � bien sa mission, cette macro va d�tok�niser son \verb|<argument>|, n'en garder que le premier token et, avec \idx\catcode, regarder s'il s'agit d'un token ayant un catcode �gal � 1. Comme \idx\catcode attend de lire un nombre, un d�veloppement maximal est lanc� et un pont d'\idx\expandafter d�tok�nise d'abord l'argument \verb|#1| puis en isole le premier token :

\showcode/\catcode`\@11
\def\ifbracefirst#1{%��*\ifbracefirst�
       \ifnum\catcode\expandafter\expandafter\expandafter
               `\expandafter\firstto@nil\detokenize{#1W}\@nil=1 % tester si son catcode est 1��*\firstto@nil�
               \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
}
\catcode`\@12

a) \ifbracefirst{123 456}{vrai}{faux}\qquad
b) \ifbracefirst{\bgroup12\egroup3 456}{vrai}{faux}\qquad
c) \ifbracefirst{{12}3 456}{vrai}{faux}\qquad
d) \ifbracefirst{1{2}3 456}{vrai}{faux}\qquad
\begingroup
\catcode`[=1 \catcode`]=2 % les crochets deviennent des accolades
e) \ifbracefirst[[]123 456][vrai][faux]��*\ifbracefirst�
\endgroup/

Le �\verb|W|�, �crit dans l'argument de \idx\detokenize, nous met � l'abri d'une erreur de compilation en cas d'\verb|<argument>| vide. Par ailleurs, comme il est assez improbable que �\verb|W|� ait un catcode 1 lorsque la macro est appel�e, un \verb|<argument>| vide donnera un test n�gatif.

Malgr� cela, ce code comporte une erreur de programmation : si l'\verb|<argument>| commence par un espace, cet espace sera ignor� par �\firstto@nil et donc, le test ��\ifbracefirst\verb*|{ {}}|� sera positif. Pour se pr�munir de ce bug, il suffit au pr�alable d'effectuer le test �\ifspacefirst et s'il est positif, agir en cons�quence.

\showcode/\catcode`\@11
\def\ifbracefirst#1{% teste si #1 commence par un token de catcode 1��*\ifbracefirst�
       \ifspacefirst{#1}% si #1 commence par un espace��*\ifspacefirst�
               {\secondoftwo}% renvoyer faux
               {\ifnum\catcode\expandafter\expandafter\expandafter
                       `\expandafter\firstto@nil\detokenize{#1W}\@nil=1 % tester si son catcode est 1��*\firstto@nil�
                       \expandafter\firstoftwo
               \else
                       \expandafter\secondoftwo
               \fi
               }%
}

\catcode`\@12
a) \ifbracefirst{}{vrai}{faux}\qquad b) \ifbracefirst{ }{vrai}{faux}\qquad
c) \ifbracefirst{ {}}{vrai}{faux}��*\ifbracefirst�/

Revenons maintenant � la macro \verb|\read@bracearg|. Voici son fonctionnement : tout d'abord, elle rajoute un token (ici \verb|\relax|) avant ce qui reste � parser. Cette pr�caution �vite que ce qui reste ne soit d�pouill� des accolades s'il s'agit d'un unique texte entre accolades. Ensuite, elle passe la main � \verb|\read@bracearg@i| dont l'argument, d�limit� par �\parsestop, est tout ce qui reste � parser. Apr�s avoir �t� le \verb|\relax|, cet argument est test� avec �\ifbracefirst. \label{parsestop.obligatoire}Remarquons que faire de �\parsestop un d�limiteur d'argument le rend \emph{obligatoire} dans la syntaxe de �\parse et introduit une contrainte assez forte. Par exemple, il ne sera pas possible de d�finir une autre s�quence de contr�le \idx\let-�gale � �\parsestop et utiliser cette macro en lieu et place de �\parsestop.

La macro �\testtoken est r�duite � sa plus simple expression : elle ne fait que rajouter le token lu au collecteur de tokens \verb|\code@toks| sans le modifier.

Pour s'assurer que le code est pars� correctement, au lieu d'�crire \verb|\the\code@toks| � la fin du processus, on a �crit �\idx\detokenize\verb-\expandafter{\the\code@toks}-� de fa�on � afficher le contenu du registre de tokens. On aurait �galement pu �crire �\idx\showthe\verb|\code@toks|� pour �crire le contenu de ce registre dans le \idx[!log]{fichier} \verb|log|.

Le code ci-dessous ne montre que la macro \verb|\read@bracearg| puisqu'elle seule a �t� modifi�e.

\showcode/\catcode`\@11
\def\parsestop@i\parsestop{% la fin va �tre atteinte
       \detokenize\expandafter{\the\code@toks}% afficher le contenu du registre�\idx*[|etc]\the\forbidindex\the�
}
\def\read@bracearg{%
       \read@bracearg@i\relax% ajoute un \relax avant de passer la main � \read@bracearg@i
}
\def\read@bracearg@i#1\parsestop{% #1 = tout jusqu'� \parsestop��*\parsestop�
       \exparg\ifbracefirst{\gobone#1}% retire le \relax et teste si #1 commence par "{"��*\exparg�*\ifbracefirst�
               {\expandafter\read@bracearg@ii\gobone#1\parsestop}% si oui, aller � \readbrace@ii��*\parsestop�
               {\expandafter\testtoken\gobone#1\parsestop}% sinon, aller � \testtoken��*\parsestop�*\testtoken�
}
\def\read@bracearg@ii#1{% lit l'argument entre accolades
       \parseadd{{#1}}% ajoute cet argument entre accolades
       \parse@i% aller lire le token suivant
}

\def\testtoken#1{%��*\testtoken�
       \parseadd{#1}% ajouter le token tel quel
       \parse@i% aller lire le token suivant
}
\catcode`\@12
\parse a\hbox\bgroup\bf braca\egroup {da}{}b{ra}\parsestop�\idx*\hbox\idx*\bgroup\idx*\bf\idx*\egroup�*\parsestop�/%

Comme nous obtenons exactement ce qui est pars�, nous avons l'assurance que la macro \verb|\read@brace| fait d�sormais correctement son travail.
\end{exercice}

\subsection{Parser aussi l'int�rieur des groupes}
Le fait que la macro �\parse n'aille pas voir � l'int�rieur des accolades est certes une r�gle que l'on s'�tait fix�e, mais on pourrait trouver utile d'ajouter une option pour que cette macro p�n�tre aussi dans les groupes entre accolades. En guise d'option, une �toile sera mise juste apr�s la macro. Pour que l'option soit stock�e quelque part, nous cr�erons un nouveau bool�en \verb|\ifparse@groups| que l'on mettra � vrai dans la version �toil�e\idx*{macro �toil�e} et � faux sinon. Ensuite, on sent bien que le n\oe ud du probl�me se trouve dans la macro \verb|\read@bracearg|, seul endroit o� le parseur s'attend � lire un argument entre accolades.

La macro \verb|\read@bracearg| doit donc �tre r��crite. Elle testera le bool�en et s'il est faux, il faudra qu'elle agisse comme pr�c�demment. S'il est vrai, \verb|\read@bracearg| doit aller parser l'argument \verb|#1| qu'elle a lu. Pour ce faire, elle ex�cutera ce code \emph{dans un groupe semi-simple} :

\centrecode-\parse*#1\parsestop-�*\parsestop

Une fois que le quark �\parsestop est atteint, il ne faut pas afficher \verb|\code@toks| comme le faisait \verb|\parsestop@i|. La macro \verb|\parsestop@i| doit donc �tre red�finie localement afin de lui faire ex�cuter la chose suivante : ajouter le contenu de \verb|\code@toks| collect� dans le groupe (sans oublier de l'envelopper d'accolades) au contenu de \verb|\code@toks| tel qu'il �tait � l'ext�rieur du groupe. Le \verb|\endgroup| fait donc partie prenant de \verb|\parsestop@i|. Afin que cet ajout soit correctement men� � bien, un pont d'\idx\expandafter sera mis en place pour retarder la sortie du groupe et d�velopper au pr�alable �\verb|\the\code@toks|� qui est l'argument de \verb|\parseadd| :

\centrecode|\expandafter\endgroup% ne fermer le groupe qu'apr�s avoir
\expandafter\parseadd% 1-d�velopp� � l'ext�rieur du groupe
\expandafter{\expandafter{\the\code@toks}}% "\the\code@toks"|

Une fois cette action effectu�e, il appartient � \verb|\parsestop@i| de poursuivre le parsing en appelant la macro \verb|\parse@i| qui lira le token suivant.

Voici le code complet :

\label{parse.a}\showcode|\catcode`\@11
\def\parsestop{\parsestop}% d�finit le quark se trouvant en fin de code��*\parsestop�
\newtoks\code@toks% alloue le registre contenant le code lu�\idx*\newtoks�
\def\parseadd#1{\code@toks\expandafter{\the\code@toks#1}}
\newif\ifparse@group�\idx*\newif�
\def\parse{%
       \code@toks{}% initialise le collecteur de tokens
       \ifstarred% teste si la macro est �toil�e��*\ifstarred�
               {\parse@grouptrue\parse@i}% mettre le bool�en � vrai
               {\parse@groupfalse\parse@i}% sinon � faux
}
\def\parse@i{\futurelet\nxttok\parse@ii}% lit le prochain token
                                       % et va � \parse@ii�\idx*\futurelet�
\def\parse@ii{%
       \ifxcase\nxttok��*\ifxcase�
               \parsestop\parsestop@i% si la fin va �tre atteinte, aller � \parsestop@i��*\parsestop�
               \sptoken\read@space% si un espace va �tre lu, aller � \read@space��*\sptoken�
               \bgroup\read@bracearg% si une accolade ouvrante  aller � \read@bracearg�\idx*\bgroup�
       \elseif��*\elseif�
               \testtoken% dans les autres cas, aller � \testtoken��*\testtoken�
       \endif��*\endif�
}
\def\parsestop@i\parsestop{% la fin est atteinte
       \the\code@toks% afficher le registre de tokens
}
\expandafter\def\expandafter\read@space\space{% \read@space mange un espace dans le code�\idx*\space�
       \testtoken{ }% et va � \testtoken��*\testtoken�
}
\def\read@bracearg{%
       \read@bracearg@i\relax% ajoute un \relax avant de passer la main � \read@bracearg@i
}
\def\read@bracearg@i#1\parsestop{% l'argument tout jusqu'� \parsestop��*\parsestop�
       \expsecond\ifbracefirst{\gobone#1}% retire le \relax et teste si #1 commence par "{"��*\ifbracefirst�*\expsecond�
               {\expandafter\read@bracearg@ii\gobone#1\parsestop}% lire l'argument entre accolades
               {\expandafter\testtoken\gobone#1\parsestop}% sinon, tester le token��*\parsestop�*\testtoken�
}
\def\read@bracearg@ii#1{% l'argument entre accolades est lu
       \ifparse@group\expandafter\firstoftwo\else\expandafter\secondoftwo\fi% si macro �toil�e
               {\begingroup% ouvre un groupe pour parser l'int�rieur de l'accolade
                       \def\parsestop@i\parsestop{% red�finir localement \parsestop@i pour
                               \expandafter\endgroup% ne fermer le groupe qu'apr�s avoir
                               \expandafter\parseadd% 1-d�velopp� � l'ext�rieur du groupe
                               \expandafter{\expandafter{\the\code@toks}}%�\idx\the�
                               \parse@i% puis va lire le token suivant
                       }%
                       \parse*#1\parsestop% <- le \parsestop@i fermera le groupe semi-simple��*\parsestop�
               }
               {\parseadd{{#1}}% macro non �toil�e, on ajoute #1 tel quel entre accolades
               \parse@i% puis va lire le token suivant
               }%
}
\def\testtoken#1{% macro qui teste le token��*\testtoken�
       \ifxcase{#1}��*\ifxcase�
               a{\parseadd{e}}
               e{\parseadd{i}}
               i{\parseadd{o}}
               o{\parseadd{u}}
               u{\parseadd{y}}
               y{\parseadd{a}}
       \elseif��*\elseif�
               \parseadd{#1}%
       \endif��*\endif�
       \parse@i% aller lire le token suivant
}
\catcode`@12
\frboxsep=1pt
a) \parse
Ce texte devenu \`a peine reconnaissable montre que le r\'esultat contient des sonorit\'es
{\bf catalanes, \frbox{corses} ou grecques} assez inattendues.��*\frbox�
\parsestop\medbreak�\idx*\medbreak�*\parsestop�

b) \parse*
Ce texte devenu \`a peine reconnaissable montre que le r\'esultat contient des sonorit\'es
{\bf catalanes, \frbox{corses} ou grecques} assez inattendues.�\idx*\bf�*\frbox�
\parsestop��*\parsestop�|

\begin{exercice}
Expliquer d'o� vient l'espace ind�sirable devant �Ci� que l'on constate lorsqu'on appelle la \idx{macro �toil�e} et proposer un rem�de pour le supprimer.
\solution

La pr�sence de l'�toile fait que le retour � la ligne qui la suit est interpr�t� comme un espace et n'est pas ignor� puisque dans ce cas, l'espace ne suit pas une s�quence de contr�le.

Il va donc falloir tester si un espace suit l'�toile et dans l'affirmative, manger cet espace avant de commencer le processus. Un simple ��\ifnexttok\verb*|{ }|� tester si un espace suit l'�toile et dans l'affirmative, cet espace sera mang� en mettant � la fin du texte de remplacement de la macro :

\centrecodespc-\afterassignment\parse@i\let\nxttok= -

Cette macro devient donc :

\showcode/\catcode`\@11
\def\parse{%
       \code@toks{}% initialise le collecteur de tokens
       \ifstarred��*\ifstarred�
               {\parse@grouptrue
               \ifnexttok{ }% si un espace suit l'�toile��*\ifnexttok�
                       {\afterassignment\parse@i% aller � \parse@i�\idx*\afterassignment�
                       \let\nxttok= }% apr�s l'avoir mang�
                       {\parse@i}% sinon, aller � \parse@i
               }
               {\parse@groupfalse
               \parse@i
               }%
}
\def\testtoken#1{% macro qui teste le token��*\testtoken�
       \ifxcase{#1}��*\ifxcase�
               a{\parseadd{e}}e{\parseadd{i}}i{\parseadd{o}}o{\parseadd{u}}
               u{\parseadd{y}}y{\parseadd{a}}
       \elseif��*\elseif�
               \parseadd{#1}%
       \endif��*\endif�
       \parse@i% aller lire le token suivant
}
\catcode`@12
\frboxsep=1pt
a) \parse
Ce texte devenu \`a peine reconnaissable montre que le r\'esultat contient des sonorit\'es
{\bf catalanes, \frbox{corses} ou grecques} assez inattendues.
\parsestop\medbreak�\idx*\medbreak�*\parsestop�
b) \parse*
Ce texte devenu \`a peine reconnaissable montre que le r\'esultat contient des sonorit\'es
{\bf catalanes, \frbox{corses} ou grecques} assez inattendues.�\idx*\bf�*\frbox�
\parsestop��*\parsestop�/
\end{exercice}\idx*[|)]{parser du code}�*\parse[|)]

\section{Rechercher, remplacer un ensemble de tokens}
Nous avions d�j� �crit la macro �\ifin � la page~\pageref{ifin} qui permettait de savoir si un texte contenait un ensemble de tokens. Nous utilisions des arguments d�limit�s et la limitation qui en d�coulait �tait que le motif cherch� ne pouvait pas contenir d'accolades. Heureusement, nous allons pouvoir contourner cette difficult� en parcourant le code token par token.

Pour parvenir � nos fins, il nous suffit de programmer une macro capable de tester si un \verb|<texet>| commence par un \verb|<motif>|.

\subsection{Un ensemble de tokens commence-t-il par un motif?}
La fabrication de la macro �\ifstartwith, dont le but est de tester si un \verb|<texte>| commence par un \verb|<motif>| va donc devenir le seul enjeu pour l'instant. En voici la syntaxe :

\centrecode-\ifstartwith{<texte>}{<motif>}{<vrai>}{<faux>}-

Avant d'en arriver � cette macro, la difficult� se concentre dans l'�criture d'une macro auxiliaire qui ampute le premier argument du texte du remplacement d'une \verb|<macro 1>| et le place dans le texte de remplacement de \verb|<macro 2>|. Le mot �argument� doit ici �tre compris dans un sens \emph{�largi} puisqu'il peut �tre un texte entre accolades, un unique token ou \emph{un espace}.

Cette macro sera baptis�e \verb|\grab@first| et admettra deux arguments qui seront des s�quences de contr�le

\centrecode-\grab@first\<macro1>\<macro2>-

\noindent Le principe va consister � tester si le texte de remplacement de \verb|\<macro1>| commence par une accolade et sinon, utiliser \idx\futurelet pour d�terminer s'il commence par un espace ou par autre chose. Selon les trois cas envisag�s, on s'orientera vers une macro qui lira convenablement le premier argument de \verb|<macro1>| et le d�placera dans \verb|\<macro2>| tout en assignant ce qu'il reste � \verb|\<macro1>|.

\showcode/\catcode`\@11
\def\grab@first#1#2{%
       \ifx#1\empty\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               {\let#2\empty% si #1 est vide, ne rien faire et assigner <vide> � #2
               }% si #1 n'est pas vide
               {\def\arg@b{#2}% stocke la macro #2 dans \arg@b
               \exparg\ifbracefirst#1% si le 1er token de #1 est "{"�\defline\aaa �*\ifbracefirst�*\exparg�
                       {\expandafter\grab@arg#1\@nil#1% aller lire l'argument avec \grab@arg
                       }
                       {% sinon, d�velopper #1 avant de le regarder avec \futurelet :
                       \expandafter\futurelet\expandafter\nxttok\expandafter\test@nxttok#1\@nil#1%�\defline\bbb\idx*\futurelet�
                       % puis aller � \test@nxttok
                       }%
               }%
}
\def\test@nxttok{% si le premier token de l'arg #1 de \grab@first est
       \ifx\nxttok\sptoken% un espace��*\sptoken�
               \expandafter\grab@spc% aller le lire avec \grab@spc
       \else
               \expandafter\grab@tok% sinon, lire le token avec \grab@tok
       \fi
}
\def\grab@arg#1{% assigne l'argument de \grab@first (mis entre accolades)
       \expandafter\def\arg@b{{#1}}% � #2
       \assign@tonil\relax% puis, assigne le reste � #1 de \grab@first
}
\expandafter\def\expandafter\grab@spc\space{%�\idx*\space�
       \expandafter\def\arg@b{ }% assigne un espace � #2 de \grab@first
       \assign@tonil\relax% puis, assigne le reste � #1 de \grab@first
}
\def\grab@tok#1{%% assigne le premier token de l'arg #1 de \grab@first
       \expandafter\def\arg@b{#1}% � la macro #2 de \grab@first
       \assign@tonil\relax% puis, assigne le reste � #1 de \grab@first
}
% assigne tout ce qui reste � lire (moins le "\relax") � la macro
% #1 de \grab@first
\def\assign@tonil#1\@nil#2{\expsecond{\def#2}{\gobone#1}}��*\expsecond�
\tt
a) \def\foo{1 {2 3} 4}\grab@first\foo\bar
  "\meaning\bar"\qquad"\meaning\foo"

b) \def\foo{ 1 {2 3} 4}\grab@first\foo\bar
  "\meaning\bar"\qquad"\meaning\foo""

c) \def\foo{{1 2} 3 4}\grab@first\foo\bar
  "\meaning\bar"\qquad"\meaning\foo"/

Revenons sur la macro \verb|\grab@first| et ses macros auxiliaires\ldots{} On constate dans son texte de remplacement que, en plus du cas trivial o� \verb|#1| est vide, l'aiguillage se fait en deux temps selon ce par quoi commence le texte de remplacement de la macro \verb|#1|. Le premier test fait concerne l'accolade ouvrante (ligne \no\aaa). Afin d'envisager tous les cas, supposons que le test est vrai : le texte de remplacement de \verb|#1| est de la forme �\verb|{<code a>}<code b>|�. L'appel suivant est alors effectu� :

\centrecode-\expandafter\grab@arg#1\@nil#1-

\noindent L'\idx\expandafter fait apparaitre ce texte de remplacement puis \verb|\grab@arg| en capture l'argument \verb|<code a>| pour le mettre dans le texte de remplacement de la macro \verb|#2|, apr�s l'avoir rhabill� d'accolades. Une fois ceci fait, il reste � lire le code suivant :

\centrecode-<code b>\@nil#1-

Rappelons-nous de ce code restant et passons maintenant � l'autre �ventualit�, celle o� le texte de remplacement de \verb|#1| ne commence pas par une accolade. Le texte de remplacement de \verb|#1| est de la forme �\verb|<token a><code b>|�. Dans ce cas, on passe la main � cette ligne :

\centrecode-\expandafter\futurelet\expandafter\nxttok\expandafter\test@nxttok#1\@nil#1-\idx*\futurelet

\noindent Tout d'abord, un pont d'\idx\expandafter d�veloppe la macro \verb|#1| pour faire apparaitre son texte de remplacement ce qui donne

\centrecode-\futurelet\nxttok\test@nxttok<token a><code b>\@nil#1-\idx*\futurelet

Ensuite, le \idx\futurelet va rendre \verb|\nxttok| \idx\let-�gal � \verb|<token a>|. La macro \verb|\test@nxttok| est appel�e par le \idx\futurelet pour tester ce qu'est \verb|<token a>| et selon qu'il est un espace ou pas, appelle \verb|\grab@spc| ou \verb|\grab@tok|. Ces deux macros capturent le \verb|<token a>| pour le mettre dans le texte de remplacement de \verb|#2| et le code qui reste � lire apr�s cette op�ration est ici encore :

\centrecode-<code b>\@nil#1-

\Qu e le texte de remplacement de \verb|#1| commence par un argument entre accolades, un espace ou un token, il reste dans tous les cas la m�me chose � lire

\centrecode|<code b>\@nil#1|

\noindent Le code �\verb|\assign@tonil\relax|� est ex�cut� � la toute fin de chacune des trois macros \verb|\grab@arg|, \verb|\grab@spc| et \verb|\grab@tok| devant ce code restant de telle sorte que l'on a form� l'appel

\centrecode-\assign@tonil\relax<code b>\@nil#1-

\noindent La macro \verb|\assign@tonil| mange ce \verb|\relax| avec \verb|\assign@tonil| puis assigne � la \verb|\<macro1>| (qui est l'argument \verb|#1|) le \verb|<code b>| et ceci termine le processus. Ouf, nous avons fait le plus dur !
\grandsaut

Ayant construit \verb|\grab@first|, il suffit ensuite pour �\ifstartwith d'extraire le premier argument �largi de \verb|<texte>| et de \verb|<motif>|, de les comparer et renvoyer \verb|<faux>| s'il ne sont pas �gaux et dans le cas contraire, recommencer jusqu'� ce que le \verb|<motif>| soit vide. � ce moment-l�, comme aucune comparaison n'a �t� fausse, il faut renvoyer \verb|<vrai>|. Le cas o� le \verb|<texte>| devient vide \emph{avant} le \verb|<motif>| doit �tre envisag�, car cela signifie que le \verb|<texte>| est plus court que le \verb|<motif>| et dans cette �ventualit�, il faut renvoyer \verb|<faux>|.

\showcode|\catcode`\@11
\def\ifstartwith#1#2{% #1=<texte>  #2=<motif>��*\ifstartwith�
       \ifempty{#2}��*\ifempty�
               \firstoftwo% si <motif> est vide, renvoyer vrai
               {\ifempty{#1}% si <code> est vide et <motif> non vide��*\ifempty�
                       \secondoftwo% renvoyer faux
                       {\def\startwith@code{#1}\def\startwith@pattern{#2}%
                       \ifstartwith@i% dans les autres cas, aller � \ifstartwith@i
                       }%
               }%
}
\def\ifstartwith@i{%
       \grab@first\startwith@code\first@code% extrait le premier "argument" de <texte>
       \grab@first\startwith@pattern\first@pattern% et celui de <motif>
       \ifx\first@code\first@pattern\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               {% si les deux arguments �largis sont �gaux
               \exparg\ifempty\startwith@pattern��*\exparg�*\ifempty�
                       \firstoftwo% et que <motif> ne contient plus rien => vrai
                       {\exparg\ifempty\startwith@code��*\exparg�*\ifempty�
                               \secondoftwo% si <texte> ne contient plus rien => faux
                               \ifstartwith@i% sinon poursuivre les tests
                       }%
               }
               \secondoftwo% si les deux argument �largis sont diff�rents, renvoyer faux
}
\catcode`\@12

1) \ifstartwith{a b c}{a b}{oui}{non}\quad 2) \ifstartwith{a b}{a b c}{oui}{non}\quad
3) \ifstartwith{ 123 }{ }{oui}{non}\quad   4) \ifstartwith{ 123 }{1}{oui}{non}\quad
5) \ifstartwith{1{2} 3}{12}{oui}{non}\quad 6) \ifstartwith{1{2} 3}{1{2} }{oui}{non}\quad
7) \ifstartwith{{} {}}{ }{oui}{non}\quad   8) \ifstartwith{{} {}}{{} }{oui}{non}\quad
9) \ifstartwith{ {12} a}{ }{oui}{non}\quad10) \ifstartwith{ {12} a}{ {1}}{oui}{non}��*\ifstartwith�|

\subsection{Un code contient-il un motif ?}
Puisque nous avons � notre disposition la macro �\ifstartwith qui sera la brique essentielle pour la suite, poursuivons avec la macro �\ifcontain dont la syntaxe est

\centrecode-\ifcontain{<texte>}{<motif>}{<vrai>}{<faux>}-

\noindent et qui renverra \verb|<vrai>| si le \verb|<texte>| contient le \verb|<motif>| et \verb|<faux>| sinon.

L'algorithme le plus na�f, que nous allons utiliser, consiste � tester si \verb|<motif>| est au d�but du \verb|<texte>|. Dans l'affirmative, il faut renvoyer \verb|<vrai>| et dans le cas contraire, manger le premier �argument �largi� de \verb|<texte>| et recommencer jusqu'� ce que \verb|<texte>| soit vide auquel cas, on renvoie \verb|<faux>|.

\showcode|\catcode`\@11
\def\ifcontain#1#2{% #1 contient-il #2?��*\ifcontain�
       \def\main@arg{#1}\def\pattern@arg{#2}% stocke le <code> et le <motif>
       \ifempty{#2}��*\ifempty�
               \firstoftwo% si #2 est vide => vrai
               {\ifempty{#1}
                       \secondoftwo% si #1 est vide et pas #2 => faux
                       \ifcontain@i% sinon, aller faire les tests
               }%
}
\def\ifcontain@i{%
       \exptwoargs\ifstartwith\main@arg\pattern@arg��*\exptwoargs�*\ifstartwith�
               \firstoftwo% si motif est au d�but de code => vrai
               {\exparg\ifempty\main@arg��*\exparg�*\ifempty�
                       \secondoftwo% sinon, si code est vide => faux
                       {\grab@first\main@arg\aux@arg% autrement, manger le 1er "argument" de code
                       \ifcontain@i% et recommencer
                       }%
               }%
}
\catcode`\@12
1) \ifcontain{abc def}{c }{oui}{non}\quad  2) \ifcontain{abc def}{cd}{oui}{non}\quad
3) \ifcontain{12 34 5}{1 }{oui}{non}\quad  4) \ifcontain{12 34 5}{ }{oui}{non}\quad
5) \ifcontain{a{b c}d}{b c}{oui}{non}\quad 6) \ifcontain{a{b c}d}{{b c}}{oui}{non}\quad
7) \ifcontain{{} {}}{ }{oui}{non}\quad     8) \ifcontain{{} {}}{{}}{oui}{non}��*\ifcontain�|

On le voit au cas \no5, la macro �\ifcontain n'inspecte pas l'int�rieur des groupes et donc, elle consid�re que le motif �\verb*|b c|� n'est pas contenu dans �\verb*|a{b c}d|�. On pourrait souhaiter que la macro �\ifcontain aille aussi voir � l'int�rieur des groupes lorsqu'elle est �toil�e\idx*{macro �toil�e}. Pour ajouter cette fonctionnalit�, il va falloir modifier la macro \verb|\ifcontain@i| pour qu'elle teste si \verb|\main@arg| commence par une accolade ouvrante et dans ce cas, agir diff�remment.

Voici l'algorithme que l'on pourrait suivre :

\begin{algo}
       \item si \verb|<motif>| est vide, renvoyer \verb|<vrai>|, sinon, si \verb|<texte>| est vide, renvoyer \verb|<faux>|. Si aucun n'est vide, aller au point \no2;
       \item initialiser le bool�en \verb|\ifin@group| � faux;
       \item si \verb|<texte>| commence par �\verb|{|�
       \begin{algo}
               \item enlever le premier argument de \verb|<texte>| et le mettre dans une macro temporaire \verb|\aux@arg|;
               \item ouvrir un groupe semi-simple;
               \item initialiser le bool�en \verb|\ifin@group| � \verb|vrai|;
               \item dans ce groupe, prendre \verb|<texte>| �gal � \verb|\aux@arg|;
               \item aller au point 3.
       \end{algo}
       \item sinon
       \begin{algo}
       \item si \verb|<motif>| est au d�but de \verb|<texte>| sortir de tous les groupes et renvoyer \verb|<vrai>|\label{sortir.tous.les.groupes};
       \item sinon
               \begin{algo}
                       \item si \verb|<texte>| est vide
                       \begin{algo}
                               \item si \verb|\ifin@group| est \verb|vrai| sortir du groupe semi-simple et aller en 3;
                               \item sinon renvoyer \verb|<faux>|;
                       \end{algo}
                       \item sinon retirer le premier argument �largi de \verb|<texte>| et aller en 3.
               \end{algo}
       \end{algo}
\end{algo}

Distribuons les t�ches. Les points 1 et 2 seront trait�s par une macro chapeau comme auparavant. Les points 3 et 4 seront �crits dans une macro r�cursive \verb|\ifcontain@star| alors que la macro r�cursive \verb|\ifcontain@nostar|, vue pr�c�demment sous le nom de \verb|\ifcontain@i| sera employ�e dans le cas ou �\ifcontain n'est pas �toil�\idx*{macro �toil�e}.

Pour le point \ref{sortir.tous.les.groupes}, nous devons �galement �crire une macro \verb|\return@true| qui ferme tous les groupes et qui renvoie \verb|<vrai>|. Le bool�en \verb|\ifin@group| rend la t�che facile puisqu'il est localement \verb|vrai| dans tous les groupes et faux � l'ext�rieur. Une simple macro r�cursive qui ferme successivement les groupes jusqu'� ce que le bool�en soit faux est suffisante :

\centrecode-\def\return@true{%
       \ifin@group% si on est dans un groupe
               \endgroup% le fermer
               \expandafter\return@true% et recommencer
       \else
               \expandafter\firstoftwo% sinon, renvoyer vrai
       \fi
}-

Voici le code complet qui en r�sulte :

\showcode|\catcode`@11
\newif\ifin@group�\idx*\newif�
\def\ifcontain{%��*\ifcontain�
       \ifstarred��*\ifstarred�
               {\in@groupfalse\ifcontain@i\ifcontain@star}%
               {\ifcontain@i\ifcontain@nostar}}

\def\ifcontain@i#1#2#3{% #1 = macro � appeler selon �toile ou pas. #2 = code. #3 = motif
       \def\main@arg{#2}\def\pattern@arg{#3}%
       \ifempty{#3}��*\ifempty�
               \firstoftwo
               {\ifempty{#2}��*\ifempty�
                       \secondoftwo
                       #1% aller � \ifcontain@star ou \ifcontain@nostar
               }%
}
\def\ifcontain@nostar{%
       \exptwoargs\ifstartwith\main@arg\pattern@arg��*\exptwoargs�*\ifstartwith�
               \firstoftwo% si motif est au d�but de code => vrai
               {\exparg\ifempty\main@arg��*\ifempty�*\exparg�
                       \secondoftwo% sinon, si code est vide => faux
                       {\grab@first\main@arg\aux@arg% autrement, manger le 1er "argument" de code
                       \ifcontain@nostar% et recommencer
                       }%
               }%
}
\def\ifcontain@star{%
       \expandafter\ifbracefirst\expandafter{\main@arg}% si code commence par "{"��*\ifbracefirst�
               {\grab@first\main@arg\aux@arg% enlever {<argument>} de main@arg
               \begingroup% ouvrir un groupe
                       \in@grouptrue% mettre le bool�en � vrai
                       \expandafter\def\expandafter\main@arg\aux@arg% assigner "argument" � \main@arg
                       \ifcontain@star% et recommencer avec ce nouveau \main@arg
               }% si code ne commence pas par "{"
               {\exptwoargs\ifstartwith\main@arg\pattern@arg% si motif est au d�but de code��*\exptwoargs�*\ifstartwith�
                       \return@true% renvoyer vrai
                       {\expandafter\ifempty\expandafter{\main@arg}% si code est vide��*\ifempty�
                               {\ifin@group% et que l'on est dans un groupe
                                       \endgroup \expandafter\ifcontain@star% en sortir et recommencer
                               \else% si on n'est pas dans un groupe, le code a �t� parcouru
                                       \expandafter\secondoftwo% sans trouver <motif> => renvoyer faux
                               \fi
                               }% si code n'est pas vide
                               {\grab@first\main@arg\startwith@code% manger le 1er "argument" de code
                               \ifcontain@star% et recommencer
                               }%
                       }%
               }%
}
\def\return@true{%
       \ifin@group% tant qu'on est dans un groupe
               \endgroup \expandafter\return@true% en sortir et recommencer
       \else
               \expandafter\firstoftwo% sinon, renvoyer vrai
       \fi
}
\catcode`@12
1) \ifcontain{ab {c d}ef}{c}{oui}{non}\quad 2) \ifcontain*{ab {c d}ef}{c}{oui}{non}��*\ifcontain�|

\subsection{Remplacer un motif par un autre}\label{substitute}�*\substitute[|(]
Il nous reste une derni�re �tape, celle de remplacer dans \verb|<texte>| un \verb|<motif a>| par un \verb|<motif b>|. La syntaxe naturelle pour une telle macro est :

\centrecode-\substitute{<texte>}{<motif a>}{<motif b>}-

La recette est connue; il nous suffit de reprendre une m�thode similaire � celle de la macro �\ifcontain (en version �toil�e\idx*{macro �toil�e} ou pas) et si le \verb|<texte>| restant � lire commence par le \verb|<motif>|, on ajoutera � un registre de tokens tenant lieu de collecteur le \verb|<motif b>|. Dans le cas contraire, il faudra ajouter � ce m�me registre le premier argument �largi du \verb|<texte>|.

Comme il n'est pas question de fermer tous les groupes d'un coup, nous allons nous passer du bool�en \verb|\ifin@group| en d�finissant une macro de fin de processus \verb|\substitute@end| qui sera appel�e lorsque \verb|<texte>| sera vide. Ce \verb|<texte>| est vide dans deux situations; soit la totalit� du texte initial a �t� pars�e, soit nous sommes dans un groupe et le \verb|<texte>| local est pars�. En dehors de tout groupe ou pour la macro non �toil�e\idx*{macro �toil�e}, la macro \verb|\substitute@end| se contentera d'afficher le contenu du registre de tokens \verb|\subst@toks| :

\centrecode-\def\substitute@end{\the\subst@toks}-

En revanche, lorsque la macro est �toil�e\idx*{macro �toil�e} et que l'on inspecte un groupe, cette macro sera modifi�e de la m�me fa�on qu'�tait modifi�e la macro \verb|\parsestop@i| : \verb|\substitute@end| devra ajouter au collecteur \verb|\subst@toks| hors du groupe ce qu'il �tait dans le groupe, apr�s l'avoir envelopp� d'accolades.

\showcode|\catcode`@11
\newtoks\subst@toks% registre de tokens pour stocker le <texte> modifi�
\def\substitute{%��*\substitute�
       \def\substitute@end{\the\subst@toks}% macro ex�cut�e � la fin
       \ifstarred��*\ifstarred�
               {\let\recurse@macro\substitute@star  \substitute@i}%
               {\let\recurse@macro\substitute@nostar\substitute@i}%
}
\def\substitute@i#1#2#3#4{% #1=macro � appeler selon �toile ou pas.
                         % #2=<texte> #3=<motif>  #4=<motif de substi>
       \def\code@arg{#2}\def\pattern@arg{#3}\def\subst@arg{#4}%
       \subst@toks={}% initialiser le collecteur � vide
       #1% aller � \substitute@star ou \substitute@nostar
}
\def\substitute@nostar{%
       \exptwoargs\ifstartwith\code@arg\pattern@arg% si le <texte> commence par <motif>�\defline\aaa�*\exptwoargs�*\ifstartwith�
               {\eaddtotoks\subst@toks\subst@arg% ajouter <motif subst>��*\eaddtotoks�
               \grab@first\code@arg\aux@code% manger le 1er "argument" de <texte>
               \substitute@nostar% et recommencer
               }
               {\expandafter\ifempty\expandafter{\code@arg}%��*\ifempty�
                       {\substitute@end% sinon, si <texte> est vide => afficher le registre de tokens
                       }
                       {\grab@first\code@arg\aux@arg% autrement, manger le 1er "argument" de <texte>
                       \eaddtotoks\subst@toks\aux@arg% et l'ajouter au registre de tokens��*\eaddtotoks�
                       \substitute@nostar% et recommencer
                       }%
               }%�\defline\bbb�
}
\def\substitute@star{%
       \expandafter\ifbracefirst\expandafter{\code@arg}% si <texte> commence par "{"��*\ifbracefirst�
               {\grab@first\code@arg\aux@arg% enlever {<argument>} de \code@arg
               \begingroup% ouvrir un groupe
                       \def\substitute@end{% modifier localement la macro ex�cut�e � la fin
                               \expandafter\endgroup\expandafter% avant de fermer le groupe
                               \addtotoks\expandafter\subst@toks\expandafter% ajouter au registre hors du groupe��*\addtotoks�
                                       {\expandafter{\the\subst@toks}}% ce qui est collect� localement, mis entre {}
                       \substitute@star% puis recommencer
                       }%
                       \subst@toks{}% initialiser � vide
                       \expandafter\def\expandafter\code@arg\aux@arg% % assigner "argument" au <texte>
                       \substitute@star% et recommencer avec ce nouveau \code@arg
               }% si code ne commence pas par "{"
               {\exptwoargs\ifstartwith\code@arg\pattern@arg% si <motif> est au d�but de <texte>�\defline\ccc�*\exptwoargs�*\ifstartwith�
                       {\eaddtotoks\subst@toks\subst@arg% ajouter <motif subst>��*\eaddtotoks�
                       \grab@first\code@arg\aux@code% manger le 1er "argument" de <texte>
                       \substitute@star% et recommencer
                       }
                       {\expandafter\ifempty\expandafter{\code@arg}% si <texte> est vide��*\ifempty�
                               {\substitute@end% aller � la macro de fin
                               }% si <texte> n'est pas vide
                               {\grab@first\code@arg\aux@code% manger le 1er "argument" de <texte>
                               \eaddtotoks\subst@toks\aux@code% et l'ajouter au registre��*\eaddtotoks�
                               \substitute@star% et recommencer
                               }%
                       }%�\defline\ddd�
               }%
}
\catcode`@12
1) \substitute{ab{\bf racada}bra}{a}{W}\qquad
2) \substitute*{ab{\bf racada}bra}{a}{W}\qquad
3) \substitute{12\frbox{\bf 34}56}{\bf}{\it}\qquad
4) \substitute*{12\frbox{\bf 34}56}{\bf}{\it}��*\frbox�|

\begin{exercice}
Dans le code propos�, les lignes \nos\aaa-\bbb{} sont identiques aux lignes \nos\ccc-\ddd{}, exception faite des macros \verb|\substitute@star| et \verb|\substitute@nostar|. Proposer une am�lioration afin de ne pas �crire deux fois cette portion de code.

D�finir une macro �\substitutetocs de syntaxe

\centrecode-\substitutetocs{<texte>}{<motif a>}{<motif b>}\<macro>-

\noindent qui assigne � \verb|\<macro>| le r�sultat de la substitution.

\solution
On peut d�finir une macro auxiliaire \verb|\recurse@macro| qui, selon que la version est �toil�e\idx*{macro �toil�e} ou non, sera \idx\let-�gale � \verb|\substitute@star| ou  \verb|\substitute@nostar|. Il suffit d�s lors de remplacer les occurrences de \verb|\substitute@star| et celles de \verb|\substitute@nostar| par \verb|\recurse@macro| et remplacer les lignes \no\ccc-\ddd{} par \verb|\substitute@nostar|.
\grandsaut

Pour cr�er �\substitutetocs, nous allons nous mettre � profit la macro \verb|\substitute@end| qui est en r�alit� un \idx[ (m�thode de programmation)]{hook}. Il sera red�fini pour que la \verb|\<macro>| (argument \verb|#4|) re�oive le contenu du registre de tokens \verb|\subst@toks|. Un \verb|\edef| peut �tre utilis� ici, car lorsque \idx\the\verb|<registre de tokens>| est plac� dans un \verb|\edef|, le contenu de ce registre \emph{non d�velopp�} apparait dans le texte de remplacement de la macro ainsi d�finie (voir page~\pageref{bloquer.developpement.maximum}).

Une fois le hook correctement d�fini, le d�roulement de la macro \verb|\subtitute| se poursuit.

\showcode|\catcode`@11
\newtoks\subst@toks% registre de tokens pour stocker le <texte> modifi�\idx\newtoks�
\def\substitute{%��*\substitute�
       \def\substitute@end{\the\subst@toks}% macro ex�cut�e � la fin
       \ifstarred��*\ifstarred�
               {\let\recurse@macro\substitute@star  \substitute@i}%
               {\let\recurse@macro\substitute@nostar\substitute@i}%
}
\def\substitute@i#1#2#3{% #1=<texte> #2=<motif> #3=<motif de substi>
       \def\code@arg{#1}\def\pattern@arg{#2}\def\subst@arg{#3}%
       \subst@toks={}% initialiser � vide
       \recurse@macro% aller � \substitute@star ou \substitute@nostar
}
\def\substitute@nostar{%
       \exptwoargs\ifstartwith\code@arg\pattern@arg% si le <texte> commence par <motif>��*\exptwoargs �*\ifstartwith�
               {\eaddtotoks\subst@toks\subst@arg% ajouter <motif subst>��\eaddtotoks�
               \grab@first\code@arg\aux@code% manger le 1er "argument" de <texte>
               \recurse@macro% et recommencer
               }
               {\expandafter\ifempty\expandafter{\code@arg}%��*\ifempty�
                       \substitute@end% sinon, si <texte> est vide => afficher le registre de tokens
                       {\grab@first\code@arg\aux@arg% autrement, manger le 1er "argument" de <texte>
                       \eaddtotoks\subst@toks\aux@arg% et l'ajouter au registre de tokens��*\eaddtotoks�
                       \recurse@macro% et recommencer
                       }%
               }%
}
\def\substitute@star{%
       \expandafter\ifbracefirst\expandafter{\code@arg}% si <texte> commence par "{"��*\ifbracefirst�
               {\grab@first\code@arg\aux@arg% enlever {<argument>} de \code@arg
               \begingroup% ouvrir un groupe
                       \def\substitute@end{% modifier localement la macro ex�cut�e � la fin
                               \expandafter\endgroup\expandafter% avant de fermer le groupe
                               \addtotoks\expandafter\subst@toks\expandafter% ajouter au registre hors du groupe��*\addtotoks�
                                       {\expandafter{\the\subst@toks}}% ce qui est collect� localement, mis entre {}�\idx*\the�
                               \recurse@macro% puis recommencer
                       }%
                       \subst@toks{}% initialiser � vide
                       \expandafter\def\expandafter\code@arg\aux@arg% % assigner "argument" au <texte>
                       \recurse@macro% et recommencer avec ce nouveau \code@arg
               }% si <texte> ne commence pas par "{" :
               \substitute@nostar% ex�cuter macro non �toil�e pour une seule it�ration
}
\def\substitutetocs{%��*\substitutetocs�
       \ifstarred��*\ifstarred�
               {\let\recurse@macro\substitute@star  \substitutetocs@i}%
               {\let\recurse@macro\substitute@nostar\substitutetocs@i}%
}
\def\substitutetocs@i#1#2#3#4{% #1=<texte> #2=<motif> #3=<motif de substi> #4=\<macro>
       \def\substitute@end{\edef#4{\the\subst@toks}}% macro ex�cut�e � la fin
       \substitute@i{#1}{#2}{#3}% continuer comme avec \substitute
}
\catcode`@12
\frboxsep=1pt
1) \substitute{ab{\bf racada}bra}{a}{W}\qquad
2) \substitute*{ab{\bf racada}bra}{a}{W}\qquad
3) \substitute{12\frbox{\bf 34}56}{\bf}{\it}\qquad
4) \substitute*{12\frbox{\bf 34}56}{\bf}{\it}��*\substitute\idx*\bf\idx*\it�*\frbox�
\medbreak

1) \substitutetocs{ab{\bf racada}bra}{a}{W}\foo       \meaning\foo\par
2) \substitutetocs*{ab{\bf racada}bra}{a}{W}\foo      \meaning\foo\par
3) \substitutetocs{12\frbox{\bf 34}56}{\bf}{\it}\foo  \meaning\foo\par
4) \substitutetocs*{12\frbox{\bf 34}56}{\bf}{\it}\foo \meaning\foo��*\substitutetocs\idx*\bf\idx*\it�*\frbox�|
\end{exercice}�*\substitute[|)]

\chapter{Des macros sur mesure}
\section{Macros � arguments optionnels}�*\vecteur[|(]
L'utilisation de �\ifnexttok va nous permettre de b�tir des macros acceptant des arguments \emph{optionnels}. Les arguments optionnels de ces macros ont vocation � se trouver entre des d�limiteurs que l'on peut choisir comme on le souhaite (parenth�ses, crochets\footnote{C'est la choix fait par \LaTeX{} et Con\TeX t.} ou autre), tout en rendant ces arguments et leurs d�limiteurs \emph{facultatifs}. En cas d'absence d'argument optionnel, un argument \emph{par d�faut}, fix� lors de la d�finition de la macro sera utilis�. Pour nous placer dans la continuit� de ce qui se fait, nous prendrons les crochets pour d�limiter les arguments optionnels.

La m�thode consiste, pour une macro chapeau, � tester avec �\ifnexttok si le prochain token est un d�limiteur ouvrant. Si tel est le cas, il faut appeler une macro auxiliaire � argument d�limit� qui va lire l'argument optionnel entre d�limiteurs. Dans le cas contraire, il faut transmettre � la macro � arguments d�limit�s un argument optionnel entre d�limiteurs que l'on choisit par d�faut.

Imaginons une macro \verb|\vecteur{<lettre>}| qui admet un argument obligatoire et qui se comporte de la fa�on suivante :

\begin{center}
\begin{tabular}{c@{ donne }c}
       \verb|\vecteur{n}|&$(x_1,\ldots,x_n)$\\
       \verb|\vecteur{k}|&$(x_1,\ldots,x_k)$\\
       \verb|\vecteur{i}|&$(x_1,\ldots,x_i)$
\end{tabular}
\end{center}

L'argument obligatoire \verb|<lettre>| est l'indice du dernier terme. On pourrait vouloir sp�cifier un argument \emph{optionnel} entre crochets qui viendrait juste apr�s la macro et qui serait l'indice du premier terme. La valeur par d�faut de cet argument serait 1. Voici comment proc�der :

\showcode/\catcode`@11
\def\vecteur{%
       \ifnexttok[% si la macro est suivie d'un crochet��*\ifnexttok�
               \vecteur@i% aller � la macro � arguments d�limit�s
               {\vecteur@i[1]}% sinon, ajouter l'argument optionnel par d�faut entre crochets
}
\def\vecteur@i[#1]#2{% #1=arg optionnel  #2=arg obligatoire
       $(x_{#1},\ldots,x_{#2})$�\idx*\ldots�
}
\catcode`@12
1) \vecteur{n}\qquad 2) \vecteur[0]{k}\qquad 3) \vecteur[i]j \qquad4) \vecteur[]n/

Bien que fonctionnant bien, on peut imaginer ce qu'il va se passer si cette macro est appel�e alors que l'on est \emph{d�j�} en mode math�matique\idx*{mode!math�matique} : le premier \verb|$| rencontr� dans la macro va faire quitter ce mode et provoquer des erreurs de compilation avec le token �\verb|_|� qui n'op�re qu'en mode math�matique. Il faut donc programmer une macro �\forcemath qui compose son argument en mode math�matique\idx*{mode!math�matique}, quel que soit le mode en cours. Pour cela, on va utiliser le test \tidx{ifmmode} qui est un test de \TeX{} :

\centrecode-\ifmmode<code vrai>\else<code faux>\fi-

Ce test est vrai si le mode math�matique\idx*{mode!math�matique} est en vigueur. C'est lorsqu'il est faux que la macro �\forcemath doit composer son argument entre d�limiteurs math�matiques �\verb|$|�.

Une autre am�lioration serait de programmer un deuxi�me argument optionnel pour sp�cifier la lettre des coordonn�es du vecteur, en choisissant $x$ par d�faut. Bien qu'il nous soit possible de le mettre entre crochets, nous allons, par souci de changement, mettre cet argument optionnel entre parenth�ses :

\showcode/\catcode`@11
\def\forcemath#1{% compose #1 en mode math, quel que soit le mode en cours��*\forcemath\idx*{mode!math�matique}�
       \ifmmode\expandafter\firstoftwo\else\expandafter\secondoftwo\fi�\tidx*{ifmmode}�
               {#1}{$#1$}%
}
\def\vecteur{%
       \ifnexttok[% si la macro est suivie d'un crochet��*\ifnexttok�
               \vecteur@i% aller � la macro � arguments d�limit�s
               {\vecteur@i[1]}% sinon, ajouter l'argument optionnel par d�faut entre crochets
}
\def\vecteur@i[#1]{%
       \ifnexttok(% si une parenth�se vient ensuite��*\ifnexttok�
               {\vecteur@ii[#1]}% aller � la macro � argument d�limit�s
               {\vecteur@ii[#1](x)}% sinon, rajouter "x" comme argument optionnel
}
\def\vecteur@ii[#1](#2)#3{% #1 et #2=arg optionnel  #3=arg obligatoire
       \forcemath{({#2}_{#1},\ldots,{#2}_{#3})}%��*\forcemath�
}
\catcode`@12
1) \vecteur{n}\qquad 2) \vecteur[0]{k}\qquad
3) \vecteur[i](y)j \qquad4) \vecteur[](\alpha)n/

\begin{exercice}
La macro \verb|\vecteur| ci-dessus admet deux arguments optionnels, mais ceux-ci doivent se trouver dans le bon ordre : celui entre crochets d'abord puis celui entre parenth�ses et enfin l'argument obligatoire. On peut �crire \verb|\vecteur[i](y){j}|, mais pas \verb|\vecteur(y)[i]{j}|.

Comment faudrait-il modifier la macro pour que les arguments optionnels puissent �tre tap�s dans n'importe quel ordre ?
\solution
Le plus simple est d'aiguiller l'algorithme vers deux �branches� selon que la macro \verb|\vecteur| est suivie d'un crochet ou d'une parenth�se. Ces deux branches seront contenues dans les macros \verb|\vecteur@bracket| et \verb|\vecteur@paren|.

\showcode/\catcode`@11
\def\vecteur{%
       \ifnexttok[% si la macro est suivie d'un crochet��*\ifnexttok�
               \vecteur@bracket% lire cet argument entre crochet
               {\ifnexttok(% sinon, si elle est suivie d'une parenth�se��*\ifnexttok�
                       \vecteur@paren % lire cet argument entre parenth�ses
                       {\vecteur@i[1](x)}% sinon, transmettre les arguments par d�faut
               }%
}
\def\vecteur@bracket[#1]{%
       \ifnexttok(% s'il y a une parenth�se apr�s��*\ifnexttok�
               {\vecteur@i[#1]}% lire la parenth�se
               {\vecteur@i[#1](x)}% sinon, donne "x" comme argument par d�faut
}
\def\vecteur@paren(#1){%
       \ifnexttok[% si le caract�re suivant est un crochet��*\ifnexttok�
               {\vecteur@ii(#1)}% lire l'argument entre crochets
               {\vecteur@ii(#1)[1]}% sinon, donner "1" comme argument par d�faut
}
\def\vecteur@i[#1](#2)#3{\forcemath{({#2}_{#1},\ldots,{#2}_{#3})}}��*\forcemath�
\def\vecteur@ii(#1)[#2]{\vecteur@i[#2](#1)}% met les arg optionnels dans l'ordre
\catcode`@12
1) \vecteur{n}\qquad 2) \vecteur[i](y){j}\qquad 3) \vecteur(y)[i]{j}\qquad
4) \vecteur[0]{k}\qquad 5) \vecteur(\alpha){n}/
\end{exercice}�*\vecteur[|)]

\section{D�finir une macro � plusieurs arguments optionnels}
La tentation est grande de cr�er une macro qui �tendrait les possibilit�s de la primitive \verb|\def| et qui permettrait de d�finir des macros avec un ou plusieurs arguments optionnels\footnote{Comme le fait la macro \texttt{\string\newcommand} de \LaTeX,  m�me si elle ne permet de d�finir qu'un seul argument optionnel.}. Afin de rester simple, nous allons devoir faire quelques sacrifices : les macros ainsi d�finies ne pourront pas �tre � arguments d�limit�s et les arguments optionnels seront entre crochets. Bien entendu, le nombre total d'arguments sera inf�rieur ou �gal � 9.

Voici la syntaxe que nous pouvons nous fixer pour la macro �\newmacro[|(] :

\centrecode-\newmacro\<macro><param�tres>{<code>}-

\noindent Les \verb|<param�tres>| sont compos�s soit de chiffres, soit de textes entre crochets. Les chiffres d�signent le nombre d'arguments obligatoires requis � cette position et les crochets un argument optionnel dont la valeur par d�faut est le code qui se trouve entre les crochets. Par exemple, si on �crit :

\centrecode-\newmacro\foo1[xxx]2[y]1{<code>}-

\noindent alors, les param�tres �\verb|1[xxx]2[y]1|� sp�cifient que la macro \verb|\foo| admet 6 arguments qui seront dans l'ordre :
\begin{itemize}
       \item un argument obligatoire;
       \item un argument optionnel dont la valeur par d�faut est �\verb|xxx|�;
       \item deux argument obligatoires;
       \item un argument optionnel dont la valeur par d�faut est �\verb|y|�;
       \item un argument obligatoire.
\end{itemize}

Le \verb|<code>| de la macro pourra contenir les arguments sous la forme habituelle \verb|#1|, \verb|#2|, etc.

\subsection{Cas particulier}
�crire d'embl�e la macro \verb|\newmacro| est un d�fi vraiment difficile. Essayons plut�t de construire � la main la macro \verb|\foo| pour bien en comprendre le fonctionnement et ensuite, nous �crirons une macro g�n�raliste \verb|\newmacro| qui b�tira automatiquement des macros admettant plusieurs arguments optionnels.

Il est bien �vident que notre macro \verb|\foo| ne va pas tenir en une seule macro. En r�alit�, � chaque fois que nous devons lui faire lire un argument optionnel, il va falloir s'assurer que le token suivant est un crochet ou pas. Par cons�quent, � ces occasions, la macro \verb|\foo| va passer la main � d'autres macros auxiliaires \verb|\foo@i|, \verb|\foo@ii|, etc.

Voici le code qui permet de construire la macro \verb|\foo| :

\showcode/\catcode`\@11
\def\foo#1{% #1 -> lit le premier argument obligatoire
       \ifnexttok[% si le token suivant est un crochet��*\ifnexttok�
               {\foo@i{#1}}% aller � \foo@i qui va lire cet argument�\defline\aaa�
               {\foo@i{#1}[xxx]}% sinon, transmettre [xxx] � foo@i�\defline\bbb�
}

\def\foo@i#1[#2]#3#4{% lit l'arg obligatoire + arg optionnel + 2 arg obligatoires
       \ifnexttok[��*\ifnexttok�
               {\foo@ii{#1}[#2]{#3}{#4}}%�\defline\ccc�
               {\foo@ii{#1}[#2]{#3}{#4}[y]}%�\defline\ddd�
}

\def\foo@ii#1[#2]#3#4[#5]#6{% lit tous les arguments
       1="#1" 2="#2" 3="#3" 4="#4" 5="#5" 6="#6"%
}

\catcode`\@12
1) \foo{arg1}{arg2}{arg3}{arg4}\par
2) \foo{arg1}[OPT\_A]{arg2}{arg3}{arg4}\par
3) \foo{arg1}{arg2}{arg3}[OPT\_B]{arg4}\par
4) \foo{arg1}[OPT\_A]{arg2}{arg3}[OPT\_B]{arg4}\medbreak�\idx*\medbreak�/

On voit donc qu'� chaque fois que l'on attend un argument optionnel, il s'agit de tester la pr�sence d'un crochet. Pour lire l'argument optionnel entre crochet, une nouvelle macro auxiliaire \verb|\foo@<n>| � argument d�limit� doit �tre cr��e. On remarque aussi que lorsque cette macro auxiliaire est appel�e (lignes \nos\aaa-\bbb{} et lignes \nos\ccc-\ddd), la \emph{totalit�} des arguments lus jusqu'� pr�sent lui est transmise. � charge pour cette macro de les lire, de lire aussi l'argument optionnel pour lequel elle est cr��e, ainsi que d'�ventuels arguments obligatoires � suivre.

Il est �galement tr�s important de remarquer que si une macro cr��e par le truchement de �\newmacro admet un ou plusieurs arguments optionnels, non seulement elle ne peut pas �tre purement d�veloppable � cause de l'emploi de \idx\futurelet, mais on ne peut pas faire apparaitre son texte de remplacement avec des \verb|\expandafter|. C'est la contrepartie qu'il faut conc�der pour profiter de la souplesse des arguments optionnels.

\subsection{Cas g�n�ral}
Pour construire la macro \verb|\newmacro|, nous allons d'abord nous mettre au clair avec les noms des macros auxiliaires. Dans le cas particulier pr�c�dent, la macro \verb|\foo| avait deux macros auxiliaires \verb|\foo@i| et \verb|\foo@ii|. Ces macros, si elles sont automatiquement cr��es par �\newmacro, posent un probl�me si l'utilisateur veut en disposer pour cr�er de lui m�me d'autres macros auxiliaires. Nous allons donc prendre le parti que si la macro � d�finir est \verb|\<macro>|, alors les macros auxiliaires seront de la forme \verb|\<macro>@[<chiffre romains>]|. Pour ce faire, une macro purement d�veloppable \verb|\macro@name{<nombre>}| se chargera de donner sous forme de tokens de catcode 12, le nom de la macro (sans caract�re d'�chappement) sous la forme \verb|<macro>@[<chiffre romains>]|.

Venons-en � la m�thode proprement dite. Elle va consister � d�finir la \idx{macro fille} \verb|\macro@name| puis � parser les \verb|<param�tres>| jusqu'� rencontrer une accolade ouvrante. Comme on l'a vu avec la macro \verb|\foo| pr�c�demment, chaque macro auxiliaire doit relire la totalit� des arguments rencontr�s jusqu'� pr�sent en y ajoutant d'autres arguments. Le \idx{texte de param�tre} de ces macros va donc s'allonger au fur et � mesure que les \verb|<param�tres>| seront pars�s. Rappelons-nous qu'avec la macro \verb|\foo|, ce texte de param�tre �tait �\verb|#1|� pour la macro principale puis �\verb|#1[#2]#3#4|� pour \verb|\foo@i| et enfin �\verb|#1[#2]#3#4[#5]#6|� pour la troisi�me macro \verb|\foo@ii|. Dans le cas g�n�ral, nous allons stocker ce texte de param�tre dans le registre de tokens \verb|\param@text|.

Lorsque les \verb|<param�tres>| sont pars�s, trois cas sont possibles selon le prochain token vu par \idx\futurelet :

\begin{enumerate}
       \item si c'est une accolade ouvrante (ou plus exactement un \idx\bgroup comme le voit \idx\futurelet), alors, c'est que le \idx{texte de param�tre} a �t� enti�rement lu;
       \item si c'est un crochet, il faut cr�er une sous-macro suppl�mentaire et ajouter � \verb|\param@text| �\hbox{\verb|[#<x>]|}� o� \hbox{\verb|<x>|} est le num�ro du prochain param�tre;
       \item dans les autres cas, il s'agit donc d'un chiffre (un unique token de 1 � 9) et il faut ajouter � \verb|\param@text| �\hbox{\verb|#<x>|}�, �\hbox{\verb|#<x+1>|}�, etc., autant de fois que le sp�cifie le chiffre lu.
\end{enumerate}

La derni�re difficult� est d'appeler les macros auxiliaires tout en leur transmettant les arguments d�j� lus sous la forme �\hbox{\verb|{#<x>}|}� si c'est un argument obligatoire et sous la forme �\hbox{\verb|[#<x>]|}� si c'est un argument optionnel. Comme les arguments obligatoires doivent �tre transmis entre accolades, le registre de tokens \verb|\param@text| ne peut pas �tre utilis�. Il faut donc utiliser un autre registre de tokens \verb|\arg@text|, mis � jour en m�me temps que \verb|\param@text| et qui enveloppera d'accolades les arguments obligatoires.

Voici donc le code, plut�t difficile, de la macro \verb|\newmacro| :

\showcode7\catcode`\@11
\newcount\macro@cnt% num�ro � mettre dans le nom des sous macros�\idx*\newcount�
\newcount\arg@cnt% compte le nombre d'arguments
\newtoks\param@text% texte de param�tre des macros sous forme "#x" et/ou "[#x]"�\idx*\newtoks�
\newtoks\arg@text% arguments sous forme "{#x}" et/ou "[#x]"

\def\newmacro#1{%
       % \macro@name construit le <nom> de la macro et �ventuellement "@[<chiffre romain>]"
       \def\macro@name##1{\expandafter\gobone\string#1\ifnum##1>0 @[\romannumeral##1]\fi}%�\idx*\romannumeral\idx*\string�
       \macro@cnt=0 \arg@cnt=0 % initialise les compteurs
       \param@text{}\arg@text{}% vide les registres de texte de param�tre et d'argument
       \newmacro@i% va voir le prochain token
}

\def\newmacro@i{\futurelet\nxttok\newmacro@ii}% met le prochain token dans \nxttok...�\idx*\futurelet�
% ...puis va � la macro :
\def\newmacro@ii{%
       \ifxcase\nxttok��*\ifxcase�
               [\newmacro@optarg% si le prochain token est un crochet aller � \newmacro@optarg
               \bgroup% si c'est un accolade ouvrante�\idx*\bgroup�
                       % le texte de param�tre est fini et il faut d�finir la macro
                       {\defname{\macro@name\macro@cnt\expandafter}%��*\defname�
                       \the\param@text}% <- le {<code>} est juste apr�s, il n'est pas encore lu�\idx*\the�
       \elseif% sinon, c'est donc un chiffre��*\elseif�
                       \newmacro@arg% aller � \newmacro@arg
       \endif��*\endif�
}

\def\newmacro@optarg[#1]{% lit la valeur par d�faut de l'argument optionnel
       % D�finit la macro \<nom>@[<nbre>] qui lit tous les arguments (optionnels ou pas)
       % jusqu'alors d�finis � l'aide de \param@text. Puis, cette macro testera si le prochain
       % token est un crochet
       \expandafter\edef\csname\macro@name\macro@cnt\expandafter\endcsname\the\param@text{%
               \noexpand\ifnexttok[%�\idx*\noexpand�*\ifnexttok\idx*\noexpand�
                       % si oui : la macro \<nom>@<nbr+1> le lira
                       {\expandafter\noexpand\csname\macro@name{\numexpr\macro@cnt+1}\expandafter\endcsname
                       \the\arg@text}%
                       % si non : transmettre � \<nom>@<nbr+1> l'argument optionnel par d�faut lu
                       {\expandafter\noexpand\csname\macro@name{\numexpr\macro@cnt+1}\expandafter\endcsname
                       \the\arg@text[\unexpanded{#1}]}%�\idx*\unexpanded�
       }%
       \advance\arg@cnt 1 % incr�menter le num�ro d'argument�\idx*\advance�
       % pour ajouter "[#<x>]" � \param@text et � \arg@text
       \eaddtotoks\param@text{\expandafter[\expandafter##\number\arg@cnt]}%��*\eaddtotoks�
       \eaddtotoks\arg@text  {\expandafter[\expandafter##\number\arg@cnt]}%��*\eaddtotoks�
       \advance\macro@cnt 1 % incr�menter le num�ro de nom de macro�\idx*\advance�
       \newmacro@i% va voir le token suivant
}

\def\newmacro@arg#1{% #1=nombre d'arguments obligatoires � ajouter
       % boucle qui ajoute "#<x>#<x+1>etc" dans \param@text
       % et "{#<x>}{#<x+1>}etc" dans \arg@text
       \ifnum#1>\z@ % tant qu'on n'a pas ajout� le nombre de #x n�cessaire�\idx*\z@�
               \advance\arg@cnt 1 % incr�menter le num�ro d'argument�\idx*\advance�
               % pour ajouter #x � \param@text et {#x} � \arg@text
               \eaddtotoks\param@text{\expandafter##\number\arg@cnt}%
               \eaddtotoks\arg@text  {\expandafter{\expandafter##\number\arg@cnt}}%��*\eaddtotoks�
               \expandafter\newmacro@arg\expandafter{\number\numexpr#1-1\expandafter}% boucler
       \else% si les arguments sont tous ajout�s
               \expandafter\newmacro@i% lire le token suivant
       \fi
}
\catcode`\@12
\newmacro\foo 1[xxx]2[y]1{1="#1" 2="#2" 3="#3" 4="#4" 5="#5" 6="#6"}
a) \foo{arg1}{arg2}{arg3}{arg4}\par
b) \foo{arg1}[OPT\_A]{arg2}{arg3}{arg4}\par
c) \foo{arg1}{arg2}{arg3}[OPT\_B]{arg4}\par
d) \foo{arg1}[OPT\_A]{arg2}{arg3}[OPT\_B]{arg4}\medbreak�\idx*\medbreak�

\meaning\foo\par
\expandafter\meaning\csname foo@[i]\endcsname\par
\expandafter\meaning\csname foo@[ii]\endcsname�\idx*\meaning�7

Il est peut �tre utile de donner quelques explications sur le code :

\begin{itemize}
       \item au chapitre des variables, le compteur \verb|\macro@cnt| sert � \verb|\macro@name| pour nommer les macros auxiliaires via \idx\romannumeral. Ces num�ros entre crochets viennent apr�s �\verb|@|� et sont �\texttt i�, �\texttt{ii}�, etc.

       Ensuite, le compteur \verb|\arg@cnt| sert � compter les arguments. Il est utilis� dans la macro \verb|\newmacro@arg| pour ins�rer dans les registres � tokens \verb|\param@text| et \verb|arg@text|, soit \verb|[#<i>]|, soit \verb|#<i>|, soit \verb|{#<i>}|;
       \item la macro \verb|\newmacro| n'est qu'une macro chapeau qui se charge des initialisations;
       \item ensuite, \verb|\newmacro@i| va voir le prochain token avec un \idx\futurelet;
       \item ce token est test� par la macro \verb|\newmacro@ii| qui d�cide ce qu'il faut faire selon les cas envisag�s plus haut :
       \begin{itemize}
               \item si ce token est un crochet, \verb|\newmacro@optarg| se charge de construire une macro auxiliaire suppl�mentaire avec un \verb|\edef| en prenant soin de ne pas d�velopper toutes les s�quences de contr�le qui ne doivent pas l'�tre. La primitive \idx\unexpanded est employ�e pour l'argument entre crochets  puisqu'il est susceptible de contenir un nombre inconnu de tokens;
               \item si ce token est un chiffre, \verb|\newmacro@arg| lit ce chiffre et met en place une r�cursivit� pour ajouter \verb|{#<x>}| et \verb|#<x>| autant de fois qu'il le faut aux registres de tokens \verb|\arg@text| et \verb|\param@text|;
               \item enfin, si ce token est une accolade ouvrante, la derni�re macro avec le texte de param�tre complet est d�finie avec le \verb|<code>| qui suit les \verb|<param�tres>|.
       \end{itemize}
\end{itemize}

Afin que les choses soient le plus claires possible et m�me si c'est fastidieux, essayons de faire mentalement fonctionner \verb|\newmacro| pour l'exemple

\centrecode|\newmacro\foo 1[xxx]2[y]1|

\noindent Par souci de clart�, les crochets autour du chiffre romain figurant dans les noms des macros auxiliaires seront omis :

\begin{enumerate}
       \item le chiffre 1 est d�tect�. Il est lu par \verb|\newmacro@arg| qui ajoute �\verb|{#1}|� et �\verb|#1|� � \verb|\arg@text| et \verb|\param@text| qui, �tant initialis�s � vide par \verb|\newmacro| contiennent donc �\verb|{#1}|� et �\verb|#1|�;
       \item un crochet est d�tect� et l'argument �\verb|[xxx]|� est lu par \verb|\newmacro@optarg| :
       \begin{itemize}
               \item elle d�finit la macro \verb|\foo| de cette fa�on :
\centrecode-\def\foo#1{%
       \ifnexttok[%��*\ifnexttok�
               {\foo@i{#1}}
               {\foo@i{#1}[xxx]}%
}-
               \item les registres \verb|\arg@text| et \verb|\param@text| sont mis � jour et contiennent �\verb|{#1}[#2]|� et �\verb|#1[#2]|�
       \end{itemize}
       \item le chiffre 2 est d�tect�. Il est lu par \verb|\newmacro@arg| qui ajoute 2 arguments �\verb|{#3}{#4}|� et �\verb|#3#4|� � \verb|\arg@text| et \verb|\param@text| qui contiennent d�sormais �\verb|{#1}[#2]{#3}{#4}|� et �\verb|#1[#2]#3#4|�;
       \item un crochet est d�tect� et l'argument �\verb|[y]|� est lu par \verb|\newmacro@optarg| :
               \begin{itemize}
               \item elle d�finit la macro \verb|\foo@i| de cette fa�on :
\centrecode-\def\foo@i#1[#2]#3#4{%
       \ifnexttok[%��*\ifnexttok�
               {\foo@ii{#1}[#2]{#3}{#4}}
               {\foo@ii{#1}[#2]{#3}{#4}[y]}%
}-
               \item les registres \verb|\arg@text| et \verb|\param@text| sont mis � jour et contiennent �\verb|{#1}[#2]{#3}{#4}[#5]|� et �\verb|#1[#2]#3#4#5|�
       \end{itemize}
       \item le chiffre 1 est d�tect�. Il est lu par \verb|\newmacro@arg| qui ajoute �\verb|{#6}|� et �\verb|#6|� � \verb|\arg@text| et \verb|\param@text|;
       \item une accolade ouvrante est lue par \idx\futurelet ce qui signe la fin du processus. Le code

       \centrecode-\defname{\macro@name\macro@cnt\expandafter}\the\param@text}-

       se d�veloppe en

       \centrecode-\def\foo@ii#1[#2]#3#4#5#6-

       Ceci est suivi du \verb|<code>| entre accolades �\verb-{|#1|#2|#3|#4|#5|#6|}-� toujours non lu ce qui signifie que la macro \verb|\foo@ii| aura ce \verb|<code>| comme texte de remplacement.
\end{enumerate}

Cet algorithme ne d�finit donc une macro \emph{que} lorsqu'un crochet est d�tect� dans les \verb|<param�tres>| ou lorsque l'accolade ouvrante marquant la fin des \verb|<param�tres>| est atteinte.

\begin{exercice}
Cr�er une macro �\framebox\label{framebox} dont la syntaxe est

\centrecode-\framebox[<lettres>]{<texte}-

\noindent et qui agit comme �\frbox mais ne trace les r�glures que selon les lettres qui figurent dans l'argument optionnel. La lettre �U� (comme �\emph{up}�) demandera � ce que la r�glure sup�rieure soit trac�e. De la m�me fa�on �D�, �L� et �R� sp�cifieront respectivement que les r�glures inf�rieures, gauche et droite soient trac�es. Par d�faut, l'argument optionnel vaut �ULRD�.
\solution
Il faut reprendre la code de �\frbox et tester avec �\ifin s'il y a lieu de tracer une r�glure et l'espace qui la s�pare du \verb|<texte>|. Afin que les \verb|<lettres>| de l'argument optionnel puisse �tre minuscules ou majuscules, la primitive \idx\uppercase sera charg�e de mettre en majuscule

\centrecode-\ifin{#1}<lettre>-

Comme cette primitive est sans effet sur les s�quences de contr�le, seuls l'argument optionnel \verb|#1| et la \verb|<lettre>| seront mis en majuscule.

\showcode/\newmacro\framebox[ULRD]1{% #1 = ULRD (Up, Down, Right, Left)��*\framebox�
% ne pas changer le mode H ou V en cours
       \hbox{% enferme dans une \hbox�\idx*\hbox�
               \uppercase{\ifin{#1}L}{\vrule width\frboxrule}{}% r�glure gauche�\idx*\uppercase\idx*\vrule�*\frboxrule�*\ifin�
               \vtop{%�\idx*\vtop�
                       \vbox{% 1er �l�ment de la \vtop�\idx*\vbox�
                               \uppercase{\ifin{#1}U}{% si la r�glure sup doit �tre trac�e�\idx*\uppercase �*\ifin�
                                       \hrule height\frboxrule% r�glure sup�rieure�\idx*\hrule�
                                       \kern\frboxsep% espace haut�\idx*\kern�
                                       }
                                       {}%
                               \hbox{%�\idx*\hbox�
                                       \uppercase{\ifin{#1}L}{\kern\frboxsep}{}% espace gauche
                                       #2% contenu
                                       \uppercase{\ifin{#1}R}{\kern\frboxsep}{}% espace droite�\idx*\uppercase�
                                       }%
                       }% puis autres �l�ments de la \vtop, sous la ligne de base
                       \uppercase{\ifin{#1}D}{%�\idx*\uppercase �*\ifin�
                               \kern\frboxsep% espace bas��*\frboxsep�
                               \hrule height\frboxrule% r�glure inf�rieure�\idx*\hrule�*\frboxrule�
                               }%
                               {}%
               }%
               \uppercase{\ifin{#1}R}{\vrule width\frboxrule}{}% r�glure droite�\idx*\uppercase\idx*\vrule�*\ifin�
       }%
}
\frboxsep=1pt ��*\frboxsep�
Boite \framebox{enti�re}, \framebox[ud]{Up down}, \framebox[LR]{Left Right},
\framebox[LU]{Left Up} et \framebox[rd]{Right Down}.��*\framebox�/
\end{exercice}�*\newmacro[|)]

\section{D�velopper les arguments d'une macro}\label{eargs}
Pour rendre l'emploi des macros encore plus agr�able et souple, nous devons maintenant chercher, lorsqu'elles sont ex�cut�es, � d�velopper comme on le souhaite leurs arguments. Nous nous limiterons aux \emph{vrais} arguments et laisserons de c�t� les arguments optionnels.

Certes, nous avons d�j� � notre disposition de �\exparg (et �\expsecond qui lui est \idx\let-�gale) ainsi que �\exptwoargs, mais ces macros ne peut 1-d�velopper qu'un seul ou deux arguments. Imaginons qu'une \verb|\<macro>| admette 5 arguments et qu'un appel � cette macro n�cessite de lui passer le premier tel quel, de 1-d�velopper le premier token du 2\ieme{} argument, de 2-d�velopper celui du 3\ieme, de 3-d�velopper celui du 4\ieme{} et de d�velopper au maximum le dernier argument. Nos macros �\exparg et �\expsecond seraient bien faibles pour y parvenir. B�tissons une macro �\eargs[|(], admettant un argument obligatoire entre crochets contenant, pour chaque argument, le nombre de d�veloppements souhait�s. Si un d�veloppement maximal est voulu, un �\verb|+|� sera sp�cifi�. Pour notre macro \verb|\<macro>|, voici la syntaxe que l'appel � cette macro prendrait :

\centrecode-\eargs[0123+]\<macro>{<arg1>}{<arg2>}{<arg3>}{<arg4>}{<arg5>}-

Du c�t� de la \TeX nique, �\eargs lira son argument entre crochet et la \verb|\<macro>|. Les autres argument seront lus un par un par une macro r�cursive. Cette macro se chargera de d�velopper correctement l'argument courant et d'ajouter le r�sultat � un registre de tokens \verb|\eargs@toks| qui jouera le r�le d'un accumulateur. Ce registre �tant initialis� avec \verb|\<macro>| par �\eargs, il contiendra � la fin cette \verb|\<macro>| et les arguments correctement d�velopp�s.

Voici l'algorithme que nous mettrons en \oe uvre :

\begingroup
\numalgofalse
\def\algoleftskip{.08\hsize}
\def\algorightskip{.08\hsize}
\algorithm[\#]{Macro \texttt{\string\eargs}}/
macro ~eargs~[#1]#2% #1= liste des n-d�veloppements  #2=macro � ex�cuter
       eargs@toks:=#2% mettre la macro dans le collecteur de tokens
       ~eargs@i~#1nil% appeler eargs@i avec la liste de n-d�veloppements
~fin~\medskip
macro ~eargs@i~#1nil% #1=liste des n-d�veloppements
       ~si~ #1 est vide
               ex�cuter eargs@toks
       ~sinon~
               ~eargs@ii~#1nil% appeler eargs@ii avec la liste de n-d�veloppements
       ~finsi~
~fin~\medskip
macro ~eargs@ii~#1#2nil#3
%#1=n-d�veloppement actuel %#2=n-d�veloppements restants #3=argument courant
       ~si~ #1="+"% si un d�veloppement maximal est demand�
               macro@temp:=d�veloppement maximal de #3
       ~sinon~
               macro@temp:=#3% mettre l'argument dans une macro
               ~pour~ i=1 to #1 ~faire~% 1-d�velopper #1 fois macro_temp
                       macro@temp:=1-d�veloppement du contenu de macro@temp
               ~finpour~
       ~finsi~
       eargs@toks:=eargs@toks+\{macro@temp\}% ajouter le r�sultat au registre
       ~eargs@i~#2nil% recommencer avec la liste des n-d�veloppements restants
~fin~
/
\endgroup

Pour nous assurer que \verb|\eargs| fonctionne bien, la macro \verb|\foo| se contente ici d'afficher les arguments qu'elle re�oit tels quels avec \idx\detokenize.

\showcode/\catcode`\@11
\newtoks\eargs@toks�\idx*\newtoks�
\newtoks\eargs@temptoks
\def\eargs[#1]#2{% #1=liste des d�veloppements  #2=macro
       \eargs@toks{#2}% mettre la macro dans le collecteur de tokens
       \expandafter\eargs@i\detokenize{#1}\@nil% appeler \eargs@i avec
                                               % la liste des developpements�\idx*\detokenize�
}

\def\eargs@i#1\@nil{% #1=liste des n-d�veloppements restant
       \ifempty{#1}% s'il n' y plus de n-d�veloppements��*\ifempty�
               {\the\eargs@toks}% ex�cuter la macro et ses arguments d�velopp�s�\idx*\the�
               {\eargs@ii#1\@nil}% sinon appeller la macro qui lit un argument
}

% #1=n-d�veloppement actuel  #2=liste des n-d�veloppements restants   #3=argument lu
\def\eargs@ii#1#2\@nil#3{%
       \if+#1% si #1="+", un \edef est demand� pour cet argument�\tidx*{if}�
               \edef\eargs@tempmacro{{#3}}% le stocker dans une macro temporaire
       \else% sinon
               \eargs@temptoks={#3}% stocker l'argument dans un registre temporaire
               \for\eargs@loop = 1 to #1\do 1 % faire #1 fois :��*\for�
                       {\eargs@temptoks=% 1-d�velopper le 1er token du registre temporaire
                               \expandafter\expandafter\expandafter{\the\eargs@temptoks}%
                       }% puis le stocker dans la macro temporaire
               \edef\eargs@tempmacro{{\the\eargs@temptoks}}%�\defline\aaa\idx*\the�
       \fi
       \eaddtotoks\eargs@toks\eargs@tempmacro% ajouter le contenu de la macro au collecteur��*\eaddtotoks�
       \eargs@i#2\@nil% appeler \eargs@i avec les n-d�veloppements restants
}
\catcode`\@12
\def\foo#1#2#3#4#5{\detokenize{1="#1" 2="#2" 3="#3" 4="#4" 5="#5"}}
\def\aaa{\bbb}\def\bbb{\ccc}\def\ccc{Bonjour}

\eargs[0123+]\foo{\aaa\bbb}{\aaa\bbb}{\aaa\bbb}{\aaa\bbb}{\aaa\bbb}./

La ligne \no\aaa{} rhabille d'accolades l'argument dument d�velopp� et, comme cela a �t� expliqu� � la page~\pageref{bloquer.developpement.maximum}, le \idx\edef ne \emph{d�veloppe pas} le contenu du registre.�*\eargs[|)]
%|                                                                            |
%|                                Fin partie 4                                |
%|____________________________________________________________________________|

% ____________________________________________________________________________
%|                                                                            |
%|                                  Partie 5                                  |
%|                                                                            |
\defpartcomment{\lettrine[lines=3,nindent=0pt]{\libertineInitialGlyph{L}}{e moment} est venu de mettre en application toutes les connaissances et les m�thodes de programmation vues dans les parties pr�c�dentes. Un effort a �t� fait pour rendre certains de ces exemples aussi proches que possibles de ceux que l'on pourrait rencontrer dans une vie d'utilisateur de \TeX{}, m�me si leur complexit� peut pour certains sembler rebutante, mais il en est ainsi, plus on s'approche de \emph{vrais} exemples, plus le niveau tend � s'�lever.}

\part{Aller plus loin}

\chapter{Du nouveau dans les arguments des macros}

\section{D�tecter des marqueurs dans l'argument d'une macro}
\subsection{Cr�er un effet entre deux marqueurs}
\Qu i n'a jamais souhait� mettre des �marqueurs� dans l'argument\idx*{argument!marqueur} d'une macro sp�cialement con�ue, de telle sorte qu'entre deux de ces marqueurs, un effet sp�cial soit obtenu ? Si l'on appelle �\detectmark cette macro, on pourrait par exemple �crire

\centrecode-\detectmark{+}{Un +argument+ o� les +marqueurs+ sont d�tect�s}-�*\detectmark

\noindent pour que ce qui est entre deux �\verb|+|� subisse un traitement que l'on peut choisir. On obtiendrait par exemple

\begin{centrage}\small
Un {\bf argument} o� les {\bf marqueurs} sont d�tect�s

{\normalsize ou}\hfill\null

Un \frboxsep=1pt \frbox{\strut argument} o� les \frbox{\strut marqueurs} sont d�tect�s
\end{centrage}

Le but est bien s�r de cr�er un raccourci pour passer de \verb|+<code>+| � \verb|{\bf<code>}| ou � \verb|\frbox{<code>}| ou � tout autre effet.
\grandsaut

Pour programmer la macro �\detectmark, l'id�e est d'agir dans un groupe, de rendre actif son premier argument qui est le caract�re �marqueur�, et de programmer ce caract�re pour obtenir l'effet souhait�. Nous utiliserons ici l'astuce du \idx\lccode et \idx\lowercase, sous r�serve que \cidx\~ soit actif au moment de la d�finition. Ceci fait, il suffira de faire lire le deuxi�me argument et ensuite, fermer le groupe.

Pour davantage de souplesse, la programmation de l'effet sera confi�e � une macro externe �\markeffect qui recevra dans son argument ce qui se trouve entre les deux marqueurs.

\showcode/\catcode`\@11
\def\detectmark#1{% #1 est le marqueur��*\detectmark�
       \begingroup
               \catcode`#1=13 % rendra #1 actif apr�s la macro
               \begingroup% pour les besoins du \lccode
                       \lccode`\~=`#1 % transforme "~" en " #1 actif"�\idx*\lccode�
                       \lowercase{\endgroup\def~##1~}{\markeffect{##1}}%�\idx*\lowercase\cidx*\~�*\markeffect�
               \detectmark@i
}
\def\detectmark@i#1{%
               #1% ex�cute le code
       \endgroup% ferme le groupe, le marqueur perd son catcode actif
}
\catcode`\@12
a) \def\markeffect#1{{\bf #1}}% met en gras��*\markeffect�
\detectmark+{Un +argument+ o� les +marqueurs+ sont d�tect�s}��*\detectmark�
\medskip�\idx*\medskip�

b) \def\markeffect#1{% met dans une boite��*\markeffect�
       \begingroup
               \frboxsep=1pt % modifie l'espacement entre texte et encadrement��*\frboxsep�
               \frbox{\strut#1}% encadre�\idx*\strut�*\frbox�
       \endgroup
}
\detectmark|{Un |argument| o� les |marqueurs| sont d�tect�s}��*\detectmark�
\medskip�\idx*\medskip�

c) \def\markeffect#1{$\vcenter{\hbox{#1}\hbox{#1}}$}% superpose 2 fois��*\markeffect\idx*\vcenter\idx*[|etc]\hbox\forbidindex\hbox�
\detectmark`{Un `argument` o� les `marqueurs` sont d�tect�s}��*\detectmark�/

La macro �\detectmark est certes bien pratique, mais elle doit cependant �tre utilis�e avec pr�caution. Tout d'abord parce qu'en l'�tat, elle ne fonctionnera pas dans l'argument d'une macro :

\showcode/\catcode`\@11
\def\detectmark#1{%��*\detectmark�
       \begingroup
               \catcode`#1=13 % rendra #1 actif apr�s la macro
               \begingroup% pour les besoins du \lccode
                       \lccode`\~=`#1 % transforme "~" en " #1 actif"�\idx*\lccode�
                       \lowercase{\endgroup\def~##1~}{\markeffect{##1}}%�\idx*\lowercase\cidx*\~�*\markeffect�%
               \detectmark@i
}
\def\detectmark@i#1{%
               #1% lit le code
       \endgroup% ferme le groupe, le marqueur perd son catcode actif
}
\catcode`\@12
\def\markeffect#1{{\bf #1}}% met en gras�\idx*\bf�*\markeffect�
\frbox{\detectmark+{Un +argument+ o� les +marqueurs+ sont d�tect�s}}��*\detectmark�*\frbox�/

La raison est toujours la m�me, mais il faut la rappeler une fois de plus : la macro �\frbox \emph{lit} son argument (pour le traiter par la suite) et d�s lors, les catcodes de tous les tokens qui le composent sont fig�s\idx*{argument!catcode fig�}. Par cons�quent, la macro interne �\detectmark, qui agit \emph{apr�s} cette cong�lation des catcodes, ne peut plus modifier celui de \verb|+| pour le rendre actif.

Mais il existe une autre limitation : nous aurions aussi pu r�ver que la macro �\markeffect agisse comme �\litterate de la page~\pageref{litterate} c'est-�-dire qu'elle affiche le code tel qu'il est �crit. L� aussi, l'�chec est assur�, et toujours  pour la m�me raison. En effet, le marqueur dans la macro �\detectmark, apr�s �tre rendu actif, a �t� programm� \emph{lire} ce qui se trouve jusqu'au prochain marqueur. Ce marqueur transmet tout ce qu'il a lu � la macro �\markeffect qui, � son tour, le \emph{lit} avant de le traiter. Ce qui est entre deux marqueurs est donc lu \emph{deux fois} avant d'�tre trait�. La cons�quence est la m�me que s'il y avait eu une seule lecture : les catcodes des tokens se trouvant entre deux marqueurs sont fig�s et il n'est plus possible de les neutraliser avec \idx\dospecials.

\subsection{Autoriser du verbatim dans l'argument d'une macro}\idx*[|(]{verbatim}
Est-il possible de trouver une m�thode permettant de faire lire une portion de texte en �\idx{verbatim}� dans l'argument d'une macro ? C'est-�-dire que les tokens faisant partie de cette portion seraient lus par la macro comme �tant tous de catcode 12. La r�ponse est oui, mais le proc�d� va �tre assez \TeX nique et de toute fa�on, la solution aura des limitations.

D�cidons pour cela de cr�er une macro �\alter dont la syntaxe serait la suivante :

\centrecode-\alter<d�limiteur>\<macro>{<argument>}-�*\alter

\noindent La \verb|\<macro>| serait alt�r�e en ce sens que si des \verb|<d�limiteurs>| sont pr�sents par paires dans son \verb|<argument>|, alors tout ce qui est entre deux d�limiteurs cons�cutifs serait compris comme �tant en mode � \idx{verbatim} �. Par exemple, �crire

\centrecode-\alter{|}\frbox{texte normal |$\ver {# batim$| texte normal}-�*\alter

\noindent produirait � l'affichage

\begin{centrage}
\leavevmode\small\frbox{texte normal {\ttfamily\string$\string\ver\ \{\#\  batim\string$} texte normal}
\end{centrage}
\grandsaut

Pour parvenir � nos fins, le principe g�n�ral est de collecter dans un registre de tokens \verb|\alter@toks| tous les tokens de l'\verb|<argument>| en prenant soin de modifier � 12 le catcode de tous les tokens qui sont entre deux occurrences du \verb|<d�limiteur>|. Une fois ceci fait, il ne reste plus qu'� donner � la \verb|\<macro>| le contenu du registre de tokens.

La macro �\alter va effectuer les actions suivantes : elle va lire deux arguments qui sont le d�limiteur et la \verb|\<macro>| � alt�rer et va les stocker pour les utiliser ult�rieurement. C'est ensuite qu'elle va effectuer une action que nous n'avons jusqu'ici jamais faite : elle va manger l'accolade ouvrante de l'\verb|<argument>| avec un \idx\let\verb*|\next= | pr�c�d� d'un \idx\afterassignment qui sp�cifiera o� aller apr�s avoir mang� cette accolade. D�s lors, le probl�me qui surgit est que l'accolade qui ferme l'\verb|<argument>| se retrouve orpheline et il faudra bien prendre en compte et g�rer cette rupture d'�quilibre � un moment. Mais poursuivons notre chemin : puisque �\alter est entr� � l'int�rieur de l'\verb|<argument>|, elle va le parcourir token par token (comme le faisait la macro �\parse) et d�cider l'action � faire en fonction du prochain token � lire (obtenu avec \idx\futurelet). Voici les cas � envisager :

\begin{itemize}
       \item accolade fermante;
       \item accolade ouvrante;
       \item espace;
       \item un \verb|<d�limiteur>|;
       \item un autre token.
\end{itemize}

Pr�cisons que la macro �\ifbracefirst ne doit pas �tre utilis�e pour tester si une accolade ouvrante est � lire, car cette macro lit la totalit� de son argument pour savoir si celui-ci commence par une accolade. Cette lecture provoque des pertes d'informations (lire page~\pageref{perte.information.lecture}) et le gel des catcodes de tous les tokens, ce qui l'exact contraire de ce qui est recherch� ici.

Comme l'\verb|<argument>| est parcouru avec \idx\futurelet, les limitations de la commande �\alter apparaissent donc : il faut que l'\verb|<argument>| ne contienne ni \idx\bgroup ni \idx\egroup, car cela provoquerait des faux positifs par le test \verb|\ifx| avec les accolades ouvrantes et fermantes.

La macro �\alter va �tre construite sur le mod�le de la macro �\parse de la page~\pageref{parse} et, comme elle doit aussi effectuer son travail � l'int�rieur de groupes entre accolades, elle va emprunter la m�thode de la \idx{macro �toil�e} \verb|\parse*| de la page~\pageref{parse.a}. Une macro de fin de processus va �tre programm�e et localement modifi�e lorsqu'un groupe entre accolades est rencontr�.

Ceci donne l'algorithme suivant :

\begin{algo}
       \item d�finir la macro de fin \verb|\alter@stop|
       \begin {algo}
               \item lire l'accolade fermante orpheline �\verb|}|�;
               \item passer � l'argument de \verb|\<macro>| le contenu de \verb|\alter@toks|
       \end {algo}
       \item lire les deux arguments \verb|<d�limiteur>| et \verb|\<macro>|
       \item manger l'accolade ouvrante qui suit
       \item initialiser \verb|\alter@toks| � vide
       \item lire avec \idx\futurelet le prochain token \verb|\alter@nxttok|
       \item tester \verb|\alter@nxttok|
       \begin {algo}
               \item si c'est une accolade fermante, la fin de l'argument est donc atteinte, aller � la macro de fin \verb|\alter@stop|
               \item si c'est un espace : absorber cet espace et ajouter un espace � \verb|\alter@toks|
               \item si c'est une accolade ouvrante
               \begin{algo}
                       \item ouvrir un groupe
                       \item modifier localement la macro de fin \verb|\alter@stop| pour qu'elle rajoute � \verb|\alter@toks| le contenu local de \verb|\alter@toks| envelopp� d'accolades puis qu'elle ferme le groupe et aille au point \no5
                       \item aller au point \no3
               \end{algo}
               \item si c'est \verb|<d�limiteur>| : ouvrir un groupe semi-simple, changer les catcodes de tous les octets pour 12, ajouter tous les tokens jusqu'� la prochaine occurrence de ce d�limiteur apr�s avoir ferm� le groupe (toutes ces op�rations sont faites par une macro � arguments d�limit�s)
               \item dans les autres cas, le token � lire ne demande aucune action particuli�re : le manger et l'ajouter � \verb|\alter@toks|
       \end{algo}
       \item dans tous les cas ci-dessous sauf le c, aller au point \no5
\end{algo}

Les cas \no b, c et e ont d�j� �t� vus avec la macro �\parse. Ici, il n'y a donc que deux cas suppl�mentaires � traiter, les cas \no a et d.

\label{alter}\showcode/\catcode`\@11
\newtoks\alter@toks% collecteur de tokens

\def\alter#1#2{% #1= d�limiteur  #2 = macro � alt�rer��*\alter�
       \let\alter@macro#2% sauvegarde la macro
       \edef\alter@restorecatcode{% restaurera le catcode de #1
               \catcode`\noexpand#1=\the\catcode`#1 }%�\idx*\noexpand\idx*\the�
       \edef\alter@tmp{\let\noexpand\alter@markertoks= \string#1}%�\idx*\string�
       \alter@tmp% et sauvegarder le d�limiteur apr�s avoir mis son catcode � 12
       \edef\alter@tmp{\def\noexpand\alter@readlitterate@i\string#1####1\string#1}%�\idx*\string\idx*\noexpand�
       % d�veloppe les \string#1 pour que les arguments d�limit�s aient
       % des d�limiteurs de catcode 12�\idx*{catcode!12\space(autre)}�
       \alter@tmp{% <- comme si on �crivait "\def\alter@readlitterate@i#1##1#1"
               \endgroup% apr�s avoir lu ##1 (tokens rendus inoffensifs), fermer le groupe
               \addtotoks\alter@toks{{\tt##1}}% ajouter ces tokens��*\addtotoks�
               \alter@i% et aller lire le prochain token
       }%
       \alter@toks{}% initialise le collecteur de tokens
       \afterassignment\alter@i% aller lire le premier token apr�s avoir�\idx*\afterassignment�
       \let\alter@tmptok= % mang� l'accolade ouvrante de l'<argument> qui suit
}

\def\alter@i{% lit le prochain token et va � \alter@ii
       \futurelet\alter@nxttok\alter@ii}%�\idx*\futurelet�

\def\alter@ii{% teste le token qui doit �tre lu
       \ifxcase\alter@nxttok% si le token � lire est��*\ifxcase�
               \egroup           \alter@stop% "}" : aller � \alterstop@i�\idx*\egroup�
               \sptoken          \alter@readspc% " " : aller � \alter@readspc��*\sptoken�
               \bgroup           \alter@readarg% "{" : aller � \alter@readarg�\idx*\bgroup�
               \alter@markertoks \alter@readlitterate% "<delimiteur>" : aller � \alter@readlitterate
       \elseif��*\elseif�
               \alter@readtok% dans les autres cas, aller � \alter@readtok
       \endif��*\endif�
}

\def\alter@readlitterate{% le prochain token est le d�limiteur
       \begingroup% ouvrir un groupe
       \for\alter@tmp=0to255\do{\catcode\alter@tmp=12 }%��*\for�
       % mettre tous les catcodes � 12
       \defactive{ }{\ }% sauf l'espace rendu actif��*\defactive�
       \doforeach\alter@tmp\in{<,>,-,`,{,},'}% pour chaque motif de ligature��*\doforeach\idx{ligature}�
                       {\unless\if\alter@tmp\alter@markertoks% s'il est diff�rent du d�limiteur�\tidx*{unless}�
                               % le rendre actif pour �viter la ligature
                               \expandafter\alter@defligchar\alter@tmp
                       \fi
                       }%
       \alter@readlitterate@i% puis aller � \alter@readlitterate@i...
       % ...qui a �t� d�finie dans \alter
}

\def\alter@defligchar#1{% d�finit le caract�re pour ne pas provoquer de ligature�\idx*{ligature}�
       \defactive#1{\string#1{}}%��*\defactive\idx*\string�
}

\expandafter\def\expandafter\alter@readspc\space{% mange un espace dans le code�\idx*\space�
       \addtotoks\alter@toks{ }% ajoute l'espace��*\addtotoks�
       \alter@i% puis lire le token suivant
}

\def\alter@readarg{% le token qui suit est "{"
       \begingroup% ouvrir un groupe
       \def\alter@stop@ii{% et modifier localement la macro appel�e � la toute fin,
       % apr�s que l'accolade fermante ait �t� mang�e (par \alterstop@i)
               \expandafter\endgroup% retarder la fermeture de groupe ouvert ci-dessus
               \expandafter\addtotoks\expandafter\alter@toks\expandafter��*\addtotoks�
                       {\expandafter{\the\alter@toks}}%�\idx*\the�
               % pour ajouter hors du groupe ce qui a �t� collect� � l'int�rieur,
               % le tout mis entre accolades
               \alter@i% puis, lire le token suivant
       }%
       \alter@toks{}% au d�but du groupe, initialiser le collecteur
       \afterassignment\alter@i% aller lire le prochain token apr�s�\idx*\afterassignment�
       \let\alter@tmptok= % avoir mang� l'accolade ouvrante
}

\def\alter@readtok#1{% le prochain token ne demande pas une action sp�ciale
       \addtotoks\alter@toks{#1}% l'ajouter au collecteur��*\addtotoks�
       \alter@i% et aller lire le token suivant
}

\def\alter@stop{% le token � lire est "}"
       \afterassignment\alter@stop@ii% aller � \alter@stop@ii apr�s�\idx*\afterassignment�
       \let\alter@tmptok= % avoir mang� l'accolade fermante
}

\def\alter@stop@ii{% donner � la \<macro> tout ce qui a �t� r�colt�
       \expandafter\alter@macro\expandafter{\the\alter@toks}%�\idx*\the�
       \alter@restorecatcode% puis restaure le catcode du d�limiteur
}
\catcode`@12

\frboxsep=1pt ��*\frboxsep�
\alter|\frbox{Texte normal - |#& }| - texte normal - |_^ ##| - texte normal}��*\frbox�
\alter=\frbox{La macro =\alter= autorise du verbatim dans
des commandes imbriqu�es \frbox{comme ici =\alter=}.}��*\alter�/

Nous avons consid�r� que la \verb|\<macro>| � alt�rer n'avait qu'un seul argument. Or, il serait commode de pouvoir alt�rer les macros � plusieurs arguments de fa�on � mettre du \idx{verbatim} dans n'importe lequel de leurs arguments. C'est ici que la macro �\identity (voir page~\pageref{identity}) peut r�soudre ce probl�me. Il suffira de placer la macro � alt�rer ainsi que ses arguments dans l'argument de �\identity :

\showcode/\def\hello#1#2{Bonjour #1 et  #2 !}
\hello{foo}{bar}\par
\alter|\identity{\hello{macro |{{{\foo|}{macro |\bar}|}}��*\alter �*\identity�/\idx*[|)]{verbatim}

\section{Modifier les catcodes des arguments d�j� lus}
La r�gle de la page~\pageref{catcode.inalterable} �tait pourtant claire : d�s que \TeX{} lit un token, il lui affecte de fa�on inalt�rable un code de cat�gorie\idx*{argument!catcode fig�}. Il �tait m�me pr�cis� que ce m�canisme est incontournable. Le titre de cette section pose donc des interrogations quant au moyen utilis�.

\subsection{Technique de ��criture-lecture�}
Ce moyen consiste � enregistrer des tokens dans un fichier auxiliaire puis lire ce fichier. En effet, lorsqu'on enregistre du code dans un fichier, celui-ci, apr�s �ventuel d�veloppement, est � d�tok�nis� �, c'est-�-dire que n'en subsistent que les caract�res (au sens d'octet) qui le formaient. Les catcodes, caract�ristiques de \TeX, sont perdus � l'enregistrement. Par la suite, lors de la lecture d'un fichier, les octets qui le composent sont lus par \TeX{} et transform�s en tokens selon le r�gime de catcode en cours � ce moment.

Cette astuce redonne � n'importe quel ensemble de tokens une sorte de virginit� puisqu'on peut les relire � n'importe quel moment --~y compris dans le texte de remplacement d'une macro~-- pour qu'ils se colorent des catcodes en vigueur.

On peut l'observer en utilisant la macro �\frbox en mettant dans son argument macro �\retokenize qui enregistre les tokens de son argument (d�j� lus par la macro �\frbox) dans un fichier puis les relit :

\showcode/\def\retokenize#1{%��*\retokenize�
       \immediate\openout\wtest=retokenize.tex % ouvre le fichier�\idx*\immediate\idx*\openout�
       \immediate\write\wtest{\unexpanded{#1}}%  y �crit l'argument�\idx*\unexpanded�
       \immediate\closeout\wtest% ferme le fichier�\idx*\immediate\idx*\closeout�
       \input retokenize.tex % lit le fichier selon les catcodes en vigueur�\idx*\input�
       \unskip% mange l'espace pr�c�demment ajout� qui provient de la fin du fichier�\idx*\unskip�
}
\frboxsep=1pt
1) \frbox{Programmer en \catcode`\~=12 \TeX{} est~facile et~utile.}\par��*\frbox�
2) \frbox{Programmer en \retokenize{\catcode`\~=12 \TeX{} est~facile} et~utile.}\par
3) \frbox{Programmer en \catcode`\~=12 \retokenize{\TeX{} est~facile} et~utile.}��*\frbox�*\retokenize�/

Le cas \no1 montre bien que �\cidx\~� ne change pas de catcode dans l'argument de la macro �\frbox puisqu'il ne prend jamais le catcode 12\idx*{catcode!12 (autre)} pour donner l'affichage �\cidx\~�. Il ne le prend pas non plus � l'ext�rieur du texte de remplacement de cette macro, car �\frbox enveloppe son argument dans des boites qui jouent le r�le de groupe.


Au contraire, les cas \nos2 et 3 mettent en �vidence que la relecture du fichier �\texttt{retokenize.tex}� se fait avec les catcodes en cours. Le fichier est lu avec \cidx\~ de catcode 12\idx*{catcode!12 (autre)} pour le cas \no2 tandis que pour le cas \no3, le changement de catcode est inclus dans le fichier ce qui ne change rien au r�sultat final.

Il faut bien avoir conscience que la relecture du fichier se fait \emph{apr�s} que l'argument de �\frbox ait �t� lu. Cette lecture d'argument s'accompagne d'irr�m�diables pertes d'information (par exemple des espaces cons�cutifs lus comme un seul espace). De plus, la lecture d'un fichier provoque une alt�ration qui lui est propre : si ce n'est pas d�j� le cas, un espace est ins�r� apr�s toute s�quence de contr�le lue dans le fichier. Cet espace ajout� n'a aucune incidence si le code est \emph{ex�cut�} car les espaces sont ignor�s lorsqu'ils suivent une s�quence de contr�le. Le seul cas o� cet espace peut devenir g�nant est lorsqu'on compose du � \idx{verbatim} � en provenance d'un fichier. L'exemple montre avec �\litterate la double alt�ration que subit le code : la premi�re rend plusieurs espaces cons�cutifs �gaux � un seul espace et l'autre ins�re un espace apr�s la macro \idx\TeX. Les deux arguments des cas \no1 et 2, bien que et  pr�sentant plusieurs diff�rences, sont rendus de la m�me fa�on :

\showcode/\frboxsep=1pt ��*\frboxsep�
1) \frbox{Programmer \retokenize{\litterate|en \TeX {} est |}facile et utile.}\par��*\frbox�*\litterate�*\retokenize�
2) \frbox{Programmer \retokenize{\litterate|en    \TeX{} est |}facile et utile.}��*\frbox�*\litterate�*\retokenize�/

\subsection{La primitive \texttt{\char`\\scantokens}}\idx*[|(]{\scantokens}
Le moteur \eTeX{}\idx*{moteur!etex} dispose de la primitive \verb|\scantokens{<texte>}| qui agit comme la macro �\retokenize avec quelques petites diff�rences :

\begin{itemize}
       \item l'�criture a lieu dans un fichier \emph{virtuel}, c'est-�-dire qu'aucun fichier n'est cr�� sur le disque dur et en r�alit�, tout se passe dans la m�moire de \eTeX{};
       \item la primitive \verb|\scantokens| est d�veloppable et son 1-d�veloppement est l'ensemble des tokens qui sont dans son argument, remis au gout du r�gime de catcode en cours;
       \item comme toutes les primitives devant �tre suivies d'une accolade, \verb|\scantokens| proc�de � un d�veloppement maximal jusqu'� rencontrer l'accolade ouvrante.
\end{itemize}

\showcode/\frboxsep=1pt ��*\frboxsep�
1) \frbox{Programmer en \catcode`\~=12 \TeX{} est~facile et~utile.}\par��*\frbox�
2) \frbox{Programmer en \scantokens{\catcode`\~=12 \TeX{} est~facile} et~utile.}\par�\idx*\scantokens�
3) \frbox{Programmer en \catcode`\~=12 \scantokens{\TeX{} est~facile} et~utile.}\par
4) \frbox{Programmer \scantokens{\litterate|en \TeX {} est facile|} et utile.}\par��*\litterate�
5) \frbox{Programmer \scantokens{\litterate|en    \TeX{} est facile|} et utile.}��*\frbox\idx*\scantokens�*\litterate�/

\begin{exercice}
Expliquer d'o� vient l'espace en trop entre les mots �facile� et �et� des cas \no2-5 de l'exemple pr�c�dent ainsi que l'espace parasite entre lettres �a� et �b� ci-dessous :

\showcode/\scantokens{a}b/
\solution
Il provient du \idx{caract�re de fin de ligne}\idx*{fin de ligne} qui est ins�r� � la fin de chaque ligne. Ici, le fichier virtuel est constitu� d'une seule ligne contenant �a� et le caract�re de code \idx\endlinechar est ins�r� � la fin de cette ligne. Par d�faut, ce caract�re est �\verbidx*[ (retour charriot)]{^^M}\verb|^^M|�, de catcode 5\idx*{catcode!5 (retour charriot)}, qui est lu comme un espace. On peut donc d�finir localement \idx\endlinechar comme entier n�gatif pour le neutraliser :

\showcode/\begingroup\endlinechar=-1 \scantokens{a}b\endgroup�\idx*\scantokens\idx*\endlinechar�/
\end{exercice}

\subsection{\texttt{\char`\\scantokens} : erreurs en vue}
Le fonctionnement est clair, mais une erreur surprenante est �mise lorsque l'on tente de d�velopper \verb|\scantokens| dans le texte de remplacement d'une macro :

\errcode/\edef\foo{\scantokens{Bonjour le monde}}% produit une erreur/{! File ended while scanning definition of \string\foo.}

\noindent Si l'on r�it�re l'exp�rience en ne la d�veloppant qu'une seule fois, la m�me erreur survient :

\errcode/\expandafter\def\expandafter\foo\expandafter
       {\scantokens{Bonjour le monde}}% produit une erreur/{! File ended while scanning definition of \string\foo.}

Il arriverait une erreur similaire si l'on �crivait :

\centrecode-\toks0=\expandafter{\scantokens{Bonjour le monde}}-\idx*\toks
\noindent et on obtiendrait �\texttt{! File ended while scanning text of \string\toks.}�

Comme \verb|\scantokens| agit un peu comme \idx\input, il en partage aussi les secrets (voir page~\pageref{input.secrets}). Le lecteur qui avait saut� la lecture de cette section ou qui n'en a plus qu'un vague souvenir est invit� � s'y replonger. L'essentiel � retenir est que la fin d'un fichier --~virtuel ou pas~-- est �\idx\outer�. Ici, \TeX{} se plaint, car cette fin de fichier se trouve � des endroits qui lui sont interdits par son statut d'\idx\outer.

Le rem�de pour la fin d'un fichier virtuel \idx\outer est le m�me que pour la fin d'un fichier r�el pr�sent dans le texte de remplacement d'une macro : il suffit de placer un \idx\noexpand juste avant la fin de ce fichier et de s'assurer qu'il sera d�velopp� \emph{avant} que la d�finition de la macro ne se fasse. Ceci implique donc qu'il \emph{faut} utiliser la macro \verb|\edef| :

\begingroup\edef\foo{Bonjour le monde}
\showcode/�\litterate|\edef\foo{\scantokens{Bonjour le monde\noexpand}}|�*\litterate\idx*\noexpand�
Voici la macro \string\foo\ : \foo.�\idx*\string�/
\endgroup

Utiliser \verb|\edef| comporte l'inconv�nient de d�velopper la totalit� de l'argument alors que finalement, seul le \idx\noexpand final aurait besoin d'�tre d�velopp�. Comme nous l'avions fait avec \idx\input, il est possible de construire une macro �\scandef ayant la syntaxe suivante

\centrecode-\scandef\<macro>{<texte>}-

\noindent et qui met le 1-d�veloppement de \verb|\scantokens{<texte>}| dans le texte de remplacement de \verb|\<macro>|. Nous allons utiliser le m�me artifice qu'avec \idx\input (voir page~\pageref{input.dans.macro}) et nous servir de \idx\everyeof pour placer un \verb|\@nil| � la fin du fichier virtuel. Ce \verb|\@nil| sera utilis� par une macro auxiliaire comme d�limiteur d'argument:

\showcode/\catcode`\@11
\def\scandef#1#2{% #1=\<macro>   #2=<texte>��*\scandef�
       \begingroup
               \endlinechar=-1 % pas de caract�re de fin de ligne�\idx*\endlinechar\idx*{caract�re de fin de ligne}�
               \everyeof{\@nil#1\noexpand}% ajoute "\@nil\<macro>\noexpand" avant la fin du fichier�\idx*\everyeof\idx*\noexpand�
               \expandafter\scandef@i\expandafter\relax\scantokens{#2}%�\idx*\scantokens�
}
\def\scandef@i#1\@nil#2{% "\@nil#2" ont �t� ajout� par \everyeof
       \endgroup% ferme le groupe
       \expandafter\def\expandafter#2\expandafter{\gobone#1}% et d�finit la \<macro>
}
\catcode`@12
\def\foo{%
       Dans tout l'argument de \string\foo, <<~>> est actif�\idx*\string�
       sauf
       \catcode`\~12
       \scandef\bar{dans celui de \string\bar : <<~>>}%�\idx*\string�*\scandef�
       \catcode`~13
       \bar
}
\foo/

\noindent Toute l'astuce r�side dans �\idx\everyeof\verb|{\@nil#1\noexpand}|� qui demande que soit ajout� avant la fin du fichier un \verb|\@nil| et la \verb|\<macro>| (qui est \verb|#1|), le tout suivi de \idx\noexpand. Par cons�quent, la ligne

\centrecode-\expandafter\scandef@i\scantokens{<texte>}-

\noindent se d�veloppe en

\centrecode-\scandef@i<texte relu par \scantokens>\@nil\<macro>\noexpand<EOF>-

\noindent et la macro � argument d�limit� \verb|\scandef@i| n'a plus qu'� saisir les arguments d�limit�s pour, une fois sorti du groupe, d�finir la \verb|\<macro>| sans jamais avoir � lire la fin du fichier \verb|<EOF>| qui de toute fa�on, est neutralis�e par \idx\noexpand.
\grandsaut

La chronologie qui se met en place lorsque \verb|\scantokens|\linebreak[1]\verb|{<code>}| est ex�cut� est la suivante :

\begin{itemize}
       \item insertion du caract�re de code \idx\endlinechar apr�s tous les retours � la ligne, y compris apr�s la derni�re;
       \item transformation du code qui en r�sulte en tokens;
       \item insertion du code contenu dans \idx\everyeof � la fin de ce qui va �tre lu par \verb|\scantokens|.
\end{itemize}

On peut constater que le point \no1 est bien celui qui est ex�cut� en premier avec ce code assez amusant o� la lettre �\verb|d|� de \idx\noexpand est ajout�e par \idx\endlinechar :

\begingroup
\edef\foo{Bonjour le monde}
\showcode/{%
\endlinechar=`\d% ins�re la lettre "d" � chaque fin de ligne�\idx*\endlinechar�
�\litterate|\edef\foo{\scantokens{Bonjour le monde\noexpan}}|�% le \noexpan(d) est incomplet
Voici la macro \string\foo\ : \foo.% fins de ligne...�\idx*\string�
}% ...comment�es pour �viter le "d"/
\endgroup

\begin{exercice}
Utiliser \verb|\scantokens| pour programmer une macro �\cprotect (le �\verb|c|� signifiant �catcode�), dont la syntaxe est

\centrecode-\cprotect\<macro>{<argument>}-

\noindent et qui appelle la \verb|\<macro>| de cette fa�on :

\centrecode-\<macro>{\scantokens{<argument>\noexpand}}-

Comme l'\verb|<argument>| est relu par \idx\scantokens, l'int�r�t de cette macro est qu'elle permet d'utiliser �\litterate dans l'\verb|<argument>|. De fa�on plus g�n�rale, �\cprotect permet de changer des catcodes dans l'\verb|<argument>| de la \verb|\<macro>|.
\solution
La primitive \verb|\scantokens| va �videmment consid�rablement simplifier la m�thode, mais va aussi changer les limites de la macro comme nous le verrons, de telle sorte que �\cprotect ne peut pas �tre qualifi� d'�quivalent de la macro �\alter vue pr�c�demment.

Tout d'abord, nous allons lire l'\verb|<argument>| apr�s avoir rendu les catcodes de tous les octets �gaux � 12, sauf celui de l'accolade ouvrante et de l'accolade fermante qui gardent leurs catcodes de 1 et 2 afin justement de pouvoir d�limiter l'argument et de rendre possible sa lecture. La suite est simple : l'argument ainsi lu sera retok�nis� par \verb|\scantokens| et donn� comme argument � la \verb|\<macro>|.

\showcode/\catcode`\@11
\def\cprotect#1{% #1 est la \<macro>��*\cprotect�
       \def\cprotect@i##1{% ##1 est l'<argument>
               \endgroup% ferme le groupe pr�c�demment ouvert
               #1{\scantokens{##1\noexpand}}%�\idx*\scantokens\idx*\noexpand�
       }%
       \begingroup% rend tous les octets de catcode12
               \for\cprotect@temp=0to255\do{\catcode\cprotect@temp=12 }%��*\for�
               \catcode`\{=1 \catcode`\}=2 % sauf "{" et "}"
               \cprotect@i% puis, lit l'argument
}
\catcode`@12
\frboxsep=1.5pt ��*\frboxsep�
1) \cprotect\frbox{foo \litterate-&#  #^   ^_%- bar}\par��*\litterate�*\frbox�
2) \cprotect\frbox{\catcode`\~=12 a~b~c~d}\par
3) \cprotect\frbox{foo \litterate-\bar- \cprotect\frbox{\litterate-&#   #-} fin}��*\cprotect�*\frbox�*\litterate�/

La macro �\cprotect, malgr� sa grande simplicit�, pr�sente trois limitations principales :

\begin{enumerate}
       \item l'\verb|<argument>| ne doit pas contenir d'accolade ouvrante ou fermante non �quilibr�e, et donc le texte trait� par �\litterate doit �galement ob�ir � cette contrainte. Y contrevenir tromperait \TeX{} sur la port�e de l'\verb|<argument>| car lors de la lecture de cet \verb|<argument>|, les accolades ont leurs catcodes normaux.
       \item �\cprotect ne peut agir que sur une macro admettant un seul argument puisque \verb|\cprotect@i| a �t� d�finie comme lisant et traitant un unique argument. Il n'est pas possible de contourner cette limitation comme on le faisait avec �\identity pour la macro �\alter. En revanche, il aurait �t� possible de programmer la macro �\cprotect diff�remment afin de mettre entre les accolades la liste des arguments de la \verb|\<macro>| :

\centrecode-\cprotect\<macro>{{argument 1}{argument 2}...}-�*\cprotect

       \item on a consid�r� que l'\verb|<argument>| �tait entre accolades, sans envisager le cas d'autres caract�res de catcode 1\idx*{catcode!1 (accolade)} ou 2. Pour bien faire, on n'aurait d� changer le catcode d'un caract�re que s'il est diff�rent de 1 ou 2. La boucle �\for aurait donc d� �tre programm�e ainsi :

\centrecode-\for\cprotect@temp=0to255\do{%
       \unless\ifnum\catcode\cprotect@temp=1
               \unless\ifnum\catcode\cprotect@temp=2
                       \catcode\cprotect@temp=12
               \fi
       \fi}-
\end{enumerate}

Selon les besoins et les limitations dont on veut s'affranchir, il convient donc de s'orienter vers �\cprotect ou �\alter.
\end{exercice}

\begin{exercice}
Comment modifier le code de �\cprotect pour permettre � la \verb|\<macro>| d'avoir plusieurs arguments et offrir la syntaxe qui est donn�e au point \no2 de la solution pr�c�dente?
\solution
Appelons �\Cprotect cette macro. La strat�gie consiste � parcourir la liste des arguments, et les stocker sous la forme

\centrecode-{\scantokens{<argument>\noexpand}}-

\noindent dans un registre de tokens qui accumulera ces arguments de telle sorte qu'� la fin du processus, ce registre contienne

\centrecode-\<macro>{\scantokens{#1\noexpand}}{\scantokens{#2\noexpand}}etc...-

\noexpand Une fois tout ceci fait, le contenu du registre sera ex�cut� avec \idx\the.

La principale difficult� est de parcourir tous les arguments et g�rer d'une fa�on ou d'une autre la fin de la liste. Ici, le \idx{quark} �\quark est mis comme dernier argument. Une macro r�cursive lira un argument � la fois et avant d'agir, fera un test pour d�terminer si tous les arguments ont �t� trait�s (cas o� l'argument lu est \verb|\ifx|-�gal � �\quark). Il faut �galement tenir compte du fait que chaque argument est d�pouill� de ses �ventuelles accolades lorsqu'il est lu par une macro.

Le registre de token \no0 tiendra lieu d'accumulateur.

\showcode/\catcode`@11
\def\Cprotect#1{% #1 est la \<macro>��*\Cprotect�
       \def\Cprotect@i##1{% ##1 est la liste des arguments
               \endgroup% ferme le groupe pr�c�demment ouvert
               \toks0={#1}% met la \<macro> dans le registre de tokens�\idx*\toks�
               \Cprotect@ii##1\quark% \quark est mis � la fin des arguments��*\quark�
               \the\toks0 % ex�cute le registre�\idx*\the\idx*\toks�
       }%
       \begingroup% rend tous les octets de catcode12
               \for\temp@arg= 0 to 255 \do{% changer � 12 tous les catcodes��*\for�
                       \unless\ifnum\catcode\temp@arg=1 % sauf si catcode=1�\tidx*{unless}�
                               \unless\ifnum\catcode\temp@arg=2 % ou 2
                                       \catcode\temp@arg=12
                               \fi
                       \fi}%
               \Cprotect@i% puis, lit l'argument
}
\def\Cprotect@ii#1{% #1 est l'argument courant (d�pouill� de ses accolades)
       \def\temp@arg{#1}% stocke l'argument pour le tester ci dessous :
       \unless\ifx\quark\temp@arg% si la fin n'est pas atteinte�\tidx*{unless} �*\quark�
               % ajouter "{\scantokens{#1\noexpand}}" au registre
               \addtotoks{\toks0}{{\scantokens{#1\noexpand}}}%��*\addtotoks\idx*\toks\idx*\noexpand�
               \expandafter\Cprotect@ii% et recommencer
       \fi
}
\catcode`@12

\def\test#1#2{Bonjour #1 et #2}
\Cprotect\test{{argument 1 : \litterate-\foo-}{argument 2 : \litterate-\bar-}}��*\Cprotect �*\litterate�/
\end{exercice}\idx*[|)]{\scantokens}

\chapter{Aller plus loin avec des r�glures}
Les r�glures, qui ne sont par d�finition que de simples rectangles noirs peuvent, moyennant un peu d'imagination, �tre utilis�es pour donner lieu � des effets plut�t originaux\ldots

\section{Cr�er une police Impact}\idx*[|(]{police Impact}
\subsection{Analyse du probl�me}
Le but ici est de cr�er de toutes pi�ces une � police � de type \impact[1pt] Impact\impactend{} comme il �tait courant d'en rencontrer du temps o� les imprimantes � aiguilles (ou matricielles) �taient encore largement majoritaires. Leur fonctionnement est d'une grande simplicit� : la t�te d'�criture est constitu�e d'une ligne de fins picots --~les aiguilles~--, tous jointifs, align�s verticalement et actionnables ind�pendamment les uns des autres. Au fur et � mesure que la t�te d'�criture se d�place par rapport � la page, les aiguilles sont bri�vement actionn�es, chacune imprimant un pixel lorsqu'elle exerce une pression sur le ruban encreur qui se trouve entre elle et la page. Voici l'effet que l'on obtient en rendant visibles les espaces entre les aiguilles :

\begin{centrage}
\impact[1.5pt][.5pt]La police Impact\impactend
\end{centrage}

La t�te de lecture a deux caract�ristiques qui lui sont donn�es lors de sa fabrication : sa hauteur et le nombre d'aiguilles. Plus les aiguilles sont en grand nombre par unit� de longueur, plus la r�solution est importante et meilleure est la qualit� d'impression.

Pr�cisons tout de suite que nous allons \emph{dessiner} des caract�res de toutes pi�ces, mais que \emph{stricto sensu}, nous n'allons pas cr�er une � \idx{police} � de caract�res. En effet, toutes les fonctionnalit�s avanc�es des \emph{vraies} \idx{police}s ne seront pas pr�sentes ici :

\begin{itemize}
       \item \idx{cr�nage}\footnote{C'est la possibilit� de modifier (souvent r�duire) l'espacement entre deux caract�res en fonction de leur forme de telle sorte que l'ensemble soit plus esth�tique. Ainsi �\hbox{AVATAR}� avec cr�nage est bien plus esth�tique que �\hbox{A{}V{}A{}T{}A{}R}� sans cr�nage. Le mot avec cr�nage a une longueur de \setbox0\hbox{AVATAR}\the\wd0 {} alors que le mot sans cr�nage mesure \setbox0\hbox{A{}V{}A{}T{}A{}R}\the\wd0.} entre caract�res;
       \item \idx{ligature}s;
       \item \idx*{coupure de mot}coupures des mots, m�me si les coupures n'ont rien � voir avec les polices, mais sont faites par \TeX{} en fonction de la position de certains groupes de lettres rencontr�s dans le mot;
       \item diff�rentes formes (italique, petites majuscules, etc.), graisse.
\end{itemize}

\noindent Il s'agit donc d'un abus de langage, certes volontaire, mais pas r�ellement malhonn�te puisqu'on pourra dessiner les caract�res que l'on veut et �crire de vraies phrases avec les dessins cr��s.

\subsection{Empilement de pixels}
Avec \TeX, ce qui va nous tenir lieu de point �l�mentaire et que nous d�nommerons �\emph{pixel}, est une simple r�glure carr�e. Contrairement aux imprimantes, nous n'imposerons aucune limite sur le nombre de pixels qui composent un caract�re, pas plus en hauteur, profondeur qu'en largeur, la seule limite �tant finalement la patience de l'utilisateur � cr�er un caract�re fait d'un grand nombre de pixels. Pour dessiner un pixel et correctement le positionner par rapport aux autres, il nous faut d�finir deux dimensions, �\pixelsize qui est le c�t� du carr� et �\pixelsep qui est l'espacement entre deux pixels adjacents, aussi bien horizontalement ou verticalement.

Autant commencer par le plus facile et d�finir la macro �\pixel qui imprime un pixel carr� en mode horizontal\idx*{mode!horizontal}, de telle sorte que le bord inf�rieur du carr� co�ncide avec la \idx{ligne de base} :

\centrecode-\def\pixel{\vrule height\pixelsize width\pixelsize depth0pt }-\idx*\vrule�*\pixelsep�*\pixelsize

Pour corser un peu plus l'exemple qui va suivre, on peut essayer d'empiler verticalement deux lignes de pixels au-dessus de la \idx{ligne de base}. Puisqu'on est au-dessus de cette \idx{ligne de base}, on va naturellement le faire dans une \idx\vbox et enfermer dans une \idx\hbox chaque ligne de pixels apr�s l'avoir convenablement s�par�e de la pr�c�dente. Pour respecter l'espacement vertical entre les deux lignes de pixels, il suffira d'annuler le ressort d'interligne avec \idx\offinterlineskip puis de r�gler ce ressort d'interligne � �\pixelsep :

\showcode/\newdimen\pixelsize \newdimen\pixelsep�\idx*\newdimen�*\pixelsep�*\pixelsize�
\def\pixel{\vrule height\pixelsize width\pixelsize depth0pt }��*\pixel�
\def\vblankpixel{\vrule height\pixelsize width0pt depth0pt }
\def\blankpixel{\vblankpixel \vrule height0pt width\pixelsize depth0pt }�\idx*\vrule�
\def\gap{\kern\pixelsep}
\pixelsize=3pt \pixelsep=1pt ��*\pixelsize�*\pixelsep�
Essai :
\vbox{% aligne verticalement�\idx*\vbox�
       \offinterlineskip% annule le ressort d'interligne�\idx*\offinterlineskip�
       \lineskip=\pixelsep\relax% pour le mettre � \pixelsep�\idx*\lineskip�*\pixelsep�
       \hbox{\pixel\gap\blankpixel\gap\blankpixel\gap\blankpixel\gap\pixel}% 1re ligne�\idx*\hbox�
       \hbox{\pixel\gap\pixel     \gap\blankpixel\gap\pixel     \gap\pixel}% 2e ligne��*\pixel�
}/

Les deux autres macros \verb|\blankpixel| et \verb|\vblankpixel| nous seront utiles par la suite et laissent un pixel blanc pour la premi�re et un strut de la hauteur d'un pixel pour la seconde. La macro \verb|\gap| ins�re une espace ins�cable de la valeur de �\pixelsep et a vocation � �tre ins�r�e  horizontalement entre deux pixels cons�cutifs, quelle que soit leurs couleurs.

Le code est clair et on comprend vite le principe. On voit ici que les pixels dessin�s pourraient former le haut de la lettre

\begin{centrage}
\impact[3pt][1pt]M\impactend
\end{centrage}

\noindent Et l'on pourrait facilement �crire les lignes suppl�mentaires n�cessaires pour afficher cette lettre en entier.

Remarquons que l'ordre d'affichage des pixels n'est pas celui des imprimantes � aiguilles : le caract�re n'est pas imprim� par une succession de lignes de pixels verticales. Bien s�r, on pourrait proc�der ainsi, mais les boites de \TeX{} nous facilitent la t�che si l'on s'y prend autrement. On va plut�t imprimer de haut en bas toutes les lignes de pixels (elles-m�mes imprim�es de gauche � droite) n�cessaires � la formation d'un caract�re.

\subsection{Prise en compte de la ligne de base}
Il faut maintenant s'int�resser au respect de la \idx{ligne de base} si nous voulons imprimer un caract�re comme \impact[1pt][0.4pt]g\impactend : il faut que le bas des pixels formant la partie inf�rieure de la boucle de la lettre �\impact[1pt][0.4pt]g\impactend� co�ncide exactement avec la \idx{ligne de base} :

\begin{centrage}
       \quitvmode\rlap{\vrule width4cm height0.15pt depth0.15pt }%
       \kern2cm \clap{\impact[3pt][1pt]g\impactend}\kern 2cm
\end{centrage}

Pour cela, la m�me m�thode que celle de �\frbox (voir page~\pageref{frbox.ligne.de.base}) va �tre d�ploy�e : une \idx\vbox sera ins�r�e au sommet d'une \idx\vtop, ce qui revient � utiliser ce sch�ma :

\centrecode|\vtop{%�\idx*\vtop�
       \offinterlineskip \lineskip=\pixelsep �\idx*\offinterlineskip\idx*\lineskip�*\pixelsep�
       \vbox{<lignes de pixels au-dessus de la ligne de base>}%�\idx*\vbox�
       <lignes de pixels au-dessous de la ligne de base>%
       }|

Voici un exemple o� nous appliquons ce sch�ma pour construire la lettre �\impact[1pt][0.4pt]g\impactend� :

\showcode/\pixelsize=3pt \pixelsep=1pt ��*\pixelsize �*\pixelsep�
Essai :
\vtop{%�\idx*\vtop�
 \offinterlineskip \lineskip=\pixelsep\relax�\idx*\lineskip\idx*\offinterlineskip�*\pixelsep�
 \vbox{%�\idx*\vbox�
   \hbox{\blankpixel\gap\pixel     \gap\pixel     \gap\pixel}%         ***�\idx*\hbox �*\pixel�
   \hbox{\pixel     \gap\blankpixel\gap\blankpixel\gap\pixel}%        *  *
   \hbox{\pixel     \gap\blankpixel\gap\blankpixel\gap\pixel}%        *  *
   \hbox{\pixel     \gap\blankpixel\gap\blankpixel\gap\pixel}%        *  *
   \hbox{\blankpixel\gap\pixel     \gap\pixel     \gap\pixel}%         ***
 }%                                                      ----ligne de base
 \hbox  {\blankpixel\gap\blankpixel\gap\blankpixel\gap\pixel}%           *
 \hbox  {\blankpixel\gap\pixel     \gap\pixel               }%         **��*\pixel�
}/

La constatation qui s'impose est que d�finir un caract�re avec cette m�thode est extr�mement fastidieux et il n'est pas acceptable de l'utiliser pour d�finir toutes les lettres de l'alphabet.

\subsection{Cr�er une macro dont la syntaxe est facile}
\subsubsection{La macro \ttfamily\char`\\makecar}
Syntaxiquement, l'id�al serait d'inventer un moyen pour �crire les lignes de pixels � visuellement � les unes � la suite des autres. Il faudrait donc b�tir une macro �\makecar qui ressemblerait � ceci

\centrecode/\makecar\<macro>{%��*\makecar�
***
*  *
*  *
*  *
***_
  *
**,}/

\noindent et qui stockerait dans \verb|\<macro>| le code expos� dans l'exemple ci-dessus qui permet de tracer la lettre �\impact[1pt][0.4pt]g\impactend�. Le caract�re �\verb|_|� signifie, s'il est pr�sent, que la ligne de pixels en cours s'ach�ve et que les lignes suivantes doivent se trouver sous la \idx{ligne de base}.

Pour s'offrir cette syntaxe, la premi�re chose � faire est de forcer \TeX{} � faire prendre en compte les espaces lorsqu'ils sont cons�cutifs ou plac�s en d�but de ligne. Ceci nous contraindra � changer localement le code de cat�gorie de l'espace � 12 pour qu'il �chappe � la r�gle qui lui est fix�e lorsque ce catcode est 10. Le retour charriot sera rendu actif et se d�veloppera en une virgule pour pouvoir utiliser par la suite la macro �\doforeach.

Enfin, il faut d�terminer si �\verb|_|� est pr�sent ou pas et si c'est le cas, scinder l'argument \verb|#2| en deux parties, chacune repr�sentant les lignes de pixels au-dessus et au-dessous de la ligne de base.

\subsubsection{La macro \ttfamily\char`\\makecar@i}
Une macro priv�e \verb|\makecar@i| traitera une de ces parties en transformant �\verb|*|� en �\pixel, �\verb*| |� en �\blankpixel et en ajoutant \idx\kern�\pixelsep apr�s chacune de ces macros, tout en ins�rant � la toute fin \idx\unkern pour annuler le dernier espace interpixel.

Par le truchement de �\doforeach, cette macro \verb|\makecar@i| appellera une autre macro auxiliaire \verb|\makecar@ii| qui sera charg�e de transformer chaque ligne de pixels (une suite de \verb|*| et \verb*| |) en une s�rie de �\pixel, �\blankpixel et �\gap. Elle enfermera le tout dans une \idx\hbox et ajoutera le code ainsi obtenu � une macro \verb|\pixabove| qui jouera le r�le de collecteur et qui sera affich�e dans la \idx\vtop chapeau � la toute fin. L'�criture du code de cette macro priv�e ne pr�sente pas de difficult� mais fait entrer en jeu quelques astuces.

\showcode/\catcode`\@11
\begingroup% dans ce groupe :�\defline\aaa�
\catcode`\ =12\relax% l'espace devient un "caract�re autre"
\catcode`\^^M=13\relax% le retour � la ligne est actif�\verbidx*[ (retour chariot)]{^^M}�
\edef^^M{\string,}% et se d�veloppe en une virgule (de catcode 12)
\global\deftok\otherspc{ }% d�finit un espace de catcode 12�\idx*\global\idx*{catcode!12\space(autre)}�*\otherspc�*\deftok�
\xdef\letter@code{% macro contenant le dessin de la lettre "e"�\idx*\gdef�
**
*  *
***
*
***}%
\endgroup�\defline\bbb�

\def\makecar@i#1{% #1 = dessin de la lettre avec les caract�res "," "*" et " "
       \doforeach\current@line\in{#1}% pour chaque ligne dans #1 :��*\doforeach�
               {\ifx\empty\current@line% si la ligne est vide�\idx*\empty�
                       \addtomacro\pixabove{\hbox{\vblankpixel}}% ajouter une fausse ligne��*\addtomacro�
               \else% sinon
                       \let\pix@line\empty% initialiser le code de la ligne � vide�\idx*\empty�
                       \expandafter\makecar@ii\current@line\quark% et la construire��*\quark�
               \fi
               }%
}

\def\makecar@ii#1{% #1=caract�re de dessin de la ligne en cours
       \ifxcase#1% si le caract�re est��*\ifxcase�
               *        {\addtomacro\pix@line\pixel}%��*\addtomacro�*\pixel�
               \otherspc{\addtomacro\pix@line\blankpixel}%��*\addtomacro�*\otherspc�*\blankpixel�
       \endif
       \ifx#1\quark% si la fin est atteinte ��*\quark�
               \addtomacro\pix@line\unkern% annuler le dernier espace interpixel�\idx*\unkern�
               \eaddtomacro\pixabove{% et encapsuler \pix@line dans une \hbox��*\eaddtomacro�
               \expandafter\hbox\expandafter{\pix@line}}%�\idx*\hbox�
       \else% si la fin n'est pas atteinte, ajouter l'espace interpixel
               \addtomacro\pix@line\gap��*\addtomacro�*\gap�
               \expandafter\makecar@ii% recommencer avec le caract�re suivant
       \fi
}
\pixelsize=3pt \pixelsep=1pt ��*\pixelsize �*\pixelsep�
\let\pixabove\empty% initialisation de la macro finale � vide
\exparg\makecar@i\letter@code% appelle la macro qui construit \pixabove�\defline\ccc�
La lettre
\vtop{% enferme le tout dans une \vtop :�\idx*\vtop�
       \offinterlineskip\lineskip=\pixelsep% ajuste l'espace interligne�\idx*\offinterlineskip\idx*\lineskip�*\pixelsep�
       \vbox{\pixabove}% affiche le caract�re cr��\idx*\vbox�
}./

La partie la plus int�ressante se situe dans le groupe semi-simple au d�but (lignes \nos\aaa{} � \bbb) o� le code de cat�gorie de l'espace est chang� � 12 et le celui du retour charriot est chang� � 13 pour qu'il devienne actif. Cette alt�ration de \verb|^^M| suppose que toutes les fins de ligne o� l'on ne souhaite pas voir ce \verb|^^M| actif soient comment�es, m�me celles que l'on ne commente habituellement pas (apr�s une s�quence de contr�le par exemple). Ces modifications locales faites, on peut donc tranquillement d�finir globalement la macro \verb|\letter@code| qui contient le code qui dessine la lettre �\verb|e|�. On profite de ce groupe pour d�finir avec �\deftok la s�quence de contr�le �\otherspc qui sera \verb|\let|-�gale � un espace de catcode 12\idx*{catcode!12 (autre)} et qui servira dans un test \verb|\ifx| plus tard.

\subsubsection{Retour sur la macro \ttfamily\char`\\makecar}
On voit maintenant comment proc�der lorsqu'il y a le marqueur �\verb|_|� qui indique que des pixels se trouvent au-dessous de la \idx{ligne de base}. Il faut s�parer le code d�finissant le caract�re en deux parties et agir de la m�me fa�on avec \verb|\makecar@i| sur chacune. Le code r�sultant de la premi�re est vou� � se retrouver dans la \idx\vbox tandis que celui r�sultant de la seconde est simplement ajout� dans la \idx\vtop chapeau.

Si une \verb|\<macro de dessin>| contient les �l�ments qui dessinent un caract�re  � l'aide de �\verb|*|�, �\verb*| |� et �\verb|^^M|� de catcode 12 et �ventuellement �\verb|_|�), la macro �\makecar, de syntaxe

\centrecode-\makecar\<macro>\<macro de dessin>-�*\makecar

\noindent se chargera de stocker dans la \verb|\<macro>| le code r�sultant de l'analyse du texte de remplacement de \verb|\<macro de dessin>|. Le texte de remplacement de \verb|\<macro>| sera constitu� de �\pixel, �\blankpixel et �\gap enferm�s dans des \idx\hbox, elles-m�mes incluses dans une \idx\vtop.

\showcode/\catcode`\@11
\begingroup% dans ce groupe :�\defline\aaa�
\catcode`\ =12\relax% l'espace devient un "caract�re autre"
\catcode`\^^M=13\relax% le retour � la ligne est actif�\verbidx*[ (retour charriot)]{^^M}�
\edef^^M{\string,}% et se d�veloppe en une virgule (de catcode 12)
\global\deftok\otherspc{ }% d�finit un espace de catcode 12�\idx*\global\idx*{catcode!12\space(autre)}�*\otherspc�*\deftok�
\xdef\letter@code{% macro contenant le dessin de la lettre "g"�\idx*\gdef�
***
*  *
*  *
*  *
***_
  *
**}%
\endgroup�\defline\bbb�

\def\makecar#1#2{% #1=nom recevant le code final  #2=macro contenant le dessin��*\makecar�
       \let\pixabove\empty \let\pixbelow\empty \let\pix@line\empty% initialise � vide�\idx*\empty�
       \exparg\ifin{#2}_% si le code contient _��*\ifin�
               {\expandafter\makecar@iii#2\@nil}% aller � \makecar@iii
               {\exparg\makecar@i{#2}}% sinon, � \makecar@i
       \edef#1{% d�finit la macro #1 comme
               \vtop{% une \vtop contenant :�\idx*\vtop�
                       \unexpanded{\offinterlineskip\lineskip\pixelsep}% r�glage d'espace inter ligne�\idx*\unexpanded\idx*\offinterlineskip\idx*\lineskip �*\pixelsep�
                       \vbox{\unexpanded\expandafter{\pixabove}}% \vbox des pixels au-dessus
                                                                % de la ligne de base�\idx*\vbox\idx*\unexpanded�
                       \unless\ifx\pixbelow\empty% s'il y a des pixels au-dessous de la baseline�\tidx*{unless}�
                               \unexpanded\expandafter{\pixbelow}% les ajouter dans la \vtop�\idx*\unexpanded�
                       \fi
                       }%
               }%
}

\def\makecar@iii#1_,#2\@nil{%
       \makecar@i{#2}% construit la partie au-dessous de la baseline
       \let\pixbelow\pixabove% et affecte le code � \pixbelow
       \let\pixabove\empty \let\pix@line\empty% r�-initialise�\idx*\empty�
       \makecar@i{#1}% construit la partie au-dessus de la baseline
}

\makecar\lettreg\letter@code��*\makecar�
\catcode`\@12
\pixelsize=3pt \pixelsep=1pt ��*\pixelsize �*\pixelsep�

Essai : \lettreg/

On voit clairement ce que fait la macro \verb|\makecar@iii|; elle construit s�par�ment les lignes de pixels se trouvant au-dessous puis au-dessus de la \idx{ligne de base} et stocke les codes obtenus dans les s�quences de contr�le \verb|\pixbelow| et \verb|\pixabove|. La macro �\makecar peut ensuite d�finir \verb|#1| en incluant \verb|\pixbelow| si elle n'est pas vide (cas o� \verb|_| n'est pas pr�sent). Cette d�finition se fait avec un \verb|\edef| en prenant soin de prot�ger avec \verb|\unexpanded| les endroits qui ne doivent pas �tre d�velopp�s.

\subsubsection{D�finir toutes les lettres}
L'�tape suivante va �tre de finaliser le tout. Il faut d'abord trouver un moyen simple de d�finir toutes les lettres de l'alphabet. La macro \verb|\impact@alphabet|, contenant le code de toutes les lettres, pourrait �tre d�finie ainsi :

\centrecode|\def\impact@alphabet{�\bioLegacyKeyGlyph{E_n_t_e_r}�
a/�\bioLegacyKeyGlyph{E_n_t_e_r}�
<dessin de la lettre a>,�\bioLegacyKeyGlyph{E_n_t_e_r}�
b/�\bioLegacyKeyGlyph{E_n_t_e_r}�
<dessin de la lettre b>,�\bioLegacyKeyGlyph{E_n_t_e_r}�
etc�\bioLegacyKeyGlyph{E_n_t_e_r}�
Z/�\bioLegacyKeyGlyph{E_n_t_e_r}�
<dessin de la lettre Z>}|

Pour que les choses soient parfaitement claires, les retours charriots ne faisant pas partie du dessin des lettres sont explicitement �crits �\bioLegacyKeyGlyph{E_n_t_e_r}�. Il est important de noter que dans le texte de remplacement de \verb|\impact@alphabet|, tous les \verb|^^M| sont actifs, \emph{mais non d�velopp�s} en une virgule. Imaginons maintenant que l'on parcoure ce texte de remplacement avec une boucle de type �\doforeach :

\centrecode-\doforeach\letter@name/\letter@code\in
   {<texte de remplacement de \code@lettre>}-

\noindent � chaque it�ration, \verb|\letter@name| va contenir

\centrecode-�\bioLegacyKeyGlyph{E_n_t_e_r}�<lettre>-

\noindent et \verb|\letter@code|

\centrecode-�\bioLegacyKeyGlyph{E_n_t_e_r}�<dessin de la lettre>-

\noindent o� les \bioLegacyKeyGlyph{E_n_t_e_r} sont ceux qui ne font pas partie du dessin de la lettre. Si l'on d�veloppe au maximum \verb|\letter@name| et \verb|\letter@code|, tous les retours charriots vont c�der leur place � une virgule, et les textes de remplacement de \verb|\letter@name| et \verb|\letter@code| seront :

\begin{centrage}
       \verb|,<lettre>|\qquad et\qquad\verb|,<dessin de la lettre>|
\end{centrage}

Il faudra donc tester si ces textes de remplacement commencent par une virgule et dans l'affirmative, la supprimer.

\showcode|\catcode`\@11
\begingroup
\expandafter\gdef\csname impact@" "\endcsname{% d�finit la lettre "espace"
       \hskip 4\pixelsize plus.5\pixelsize minus.5\pixelsize\relax}%
\catcode`\^^M=13\relax% le retour � la ligne est actif�\verbidx*[ (retour charriot)]{^^M}�
\edef^^M{\string,}% et se d�veloppe en une virgule (de catcode 12)
\catcode`\ =12\relax% l'espace devient un "caract�re autre"
\gdef\impact@alphabet{
a/
***
  *
***
*  *
****,
b/
*
*
***
*  *
*  *
*  *
***,
% beaucoup de caract�res omis
9/
***
*   *
*   *
****
   *
   *
***,
0/
***
*   *
*   *
* * *
*   *
*   *
***,
error/
* * *
* *
* * *
* *
* * *
* *
* * *}% <- commenter la fin de ligne
\endgroup%
% On parcourt le texte de remplacement de \impact@alphabet
\edef\saved@crcatcode{\catcode13=\the\catcode13\relax}%
\catcode`\^^M=13\relax% le retour � la ligne est actif�\verbidx*[ (retour charriot)]{^^M}�
\edef^^M{\string,}% et se d�veloppe en une virgule (de catcode 12)
\expsecond{\doforeach\letter@name/\letter@code\in}\impact@alphabet%��*\expsecond �*\doforeach�
       {\edef\letter@name{\letter@name}% d�veloppe la lettre (^^M devient ",")
       \edef\letter@code{\letter@code}% d�veloppe le code (^^M devient ",")
       \exparg\ifstart\letter@name,% si la lettre commence par ","
               {\edef\letter@name{\expandafter\gobone\letter@name}}% la retirer
               {}%
       \exparg\ifstart\letter@code,% si le code commence par ","
               {\edef\letter@code{\expandafter\gobone\letter@code}}% la retirer
               {}%
       \expandafter\makecar\csname impact@"\letter@name"\endcsname\letter@code%��*\makecar\defline\aaa�
       }%
\saved@crcatcode% redonne le catcode de ^^M
% % d�finit l'espace
\pixelsize=3pt \pixelsep=1pt ��*\pixelsize �*\pixelsep�
% puis, on affiche ce qui a �t� d�fini :
a = \csname impact@"a"\endcsname\qquad b = \csname impact@"b"\endcsname\qquad
9 = \csname impact@"9"\endcsname \qquad 0 = \csname impact@"0"\endcsname\qquad
error = \csname impact@"error"\endcsname|

La m�thode fonctionne correctement pour les caract�res d�finis : bien �videmment, pour �viter un tr�s long listing, seuls quelques uns sont d�finis ici.

Dans le code it�r� de la boucle �\doforeach, remarquons � la ligne \no\aaa{} que \verb|\makecar| est invoqu� et la macro contenant le code qui dessine le caract�re �\verb|<car>|� est \verb|\impact@"<car>"|. Notons �galement que l'espace est d�fini comme un ressort horizontal de dimension fixe �gale � 4 fois celle de �\pixelsize mais contenant aussi des composantes �tirables �gales � la moiti� de �\pixelsize. Celles-ci peuvent entrer en jeu pour justifier le texte � composer � la largeur disponible en comblant la diff�rence entre la largeur des caract�res affich�s sur la ligne et la largeur de composition.

Un caract�re �\verb|error|� a �galement �t� dessin� au cas o� l'on rencontrerait une lettre non d�finie.

\subsubsection{La macro \ttfamily\char`\\impact}
Tout cela va permettre de d�finir deux macros �\impact et \verb|\impactend| qui vont composer en police \impact Impact\impactend{} le \verb|<texte>| se trouvant entre elles selon cette syntaxe :

\centrecode/\impact[1.2pt][0.2pt]Programmer en {TEX} est
facile et tr{e`}s utile !\impactend/

Tout d'abord, pour composer ce livre, un caract�re de la police impact dont le nom est �TEX� a �t� d�fini et le fait qu'il soit �crit entre accolades assure que l'ensemble est bien lu comme un argument et compris comme le nom d'un caract�re. Le m�me principe s'applique aux caract�res accentu�s �\verb|e`|�, �\verb|e'|� et d'autres. Ensuite, la macro �\impact a deux arguments optionnels, le premier �tant la dimension qui sera assign�e � �\pixelsize et le second celle qui sera assign�e � �\pixelsep. La macro �\newmacro que nous avons vue � la partie pr�c�dente sera utilis�e afin que ces arguments optionnels soient facilement accessibles.

En reprenant la proc�dure mise en \oe uvre pour la macro �\parse, nous allons parcourir ce qui se trouve apr�s la macro �\impact et, � l'aide de \idx\futurelet, nous d�ciderons quelle action entreprendre selon le type de token � venir :
\begin{enumerate}
       \item le \idx{quark} \verb|\impactend|;
       \item un espace;
       \item un argument commen�ant par une accolade.
\end{enumerate}

Le premier cas stoppera la lecture du texte. Pour les deux derniers cas, on ins�rera apr�s chaque caract�re une espace qui est en r�alit� le ressort \verb|\letter@skip| d�fini par

\centrecode-\letter@skip=\pixelsep plus.1\pixelsize minus.1\pixelsize-�*\pixelsep

\noindent Les composantes de compression et d'�tirement de l'espace interlettre, cumul�es avec celles du caract�re intermot �\verb*|\letter@" "|�, assurent que les avertissements\idx*{message d'avertissement} de type \verb|Overful|/\linebreak[1]\verb|Underful hbox| qui caract�risent les lignes trop longues ou trop courtes seront le plus rare possible.

La fa�on de coder ce genre de macro a �t� vue � la partie pr�c�dente et il suffit de reproduire le sch�ma d�j� �tudi� :

\showcode|\catcode`\@11
\newskip\letter@skip% ressort mis entre chaque lettre�\idx*\newskip�
\def\impactend{\impactend}% d�finit le quark de fin

\newmacro\impact[0.2ex][0pt]{% d�finit la macro � arguments optionnels��*\impact�*\newmacro�
       \leavevmode% passer en mode horizontal�\idx*\leavevmode�
       \begingroup% dans un groupe semi-simple :
               \pixelsize=#1\relax \pixelsep=#2\relax% d�finir ces deux dimensions��*\pixelsize �*\pixelsep�
               \letter@skip=#1 plus.1\pixelsize minus.1\pixelsize\relax% d�finir espace inter-lettre
               \baselineskip=% d�finir la distance entre les lignes de base�\idx*\baselineskip�
                       \dimexpr12\pixelsize+7\pixelsep\relax% � 12\pixelsize+7\pixelsep
               \lineskiplimit=0pt % si lignes trop serr�es�\idx*\lineskiplimit�
               \lineskip=2\pixelsize\relax% les espacer de 2\pixelsize�\idx*\lineskip�
               \impact@i% puis aller voir le prochain token
}

% va voir le prochain token puis va le tester � \impact@ii
\def\impact@i{\futurelet\nxtletter\impact@ii}�\idx*\futurelet�

\def\impact@ii{%
               \ifx\nxtletter\impactend% si le token est \let �gal � \impactend
                       \let\donext\impact@endprocess% aller � al macro de fin
               \else
                       \ifx\nxtletter\sptoken% si c'est un espace��*\sptoken�
                               \let\donext\impact@spc% aller � \impact@spc
                       \else
                               \let\donext\impact@arg% sinon, aller � \impact@arg
                       \fi
               \fi
               \donext% faire l'action d�cid�e ci-dessus
}

% mange un espace (argument d�limit�) et affiche "\letter@<spc>"
\expandafter\def\expandafter\impact@spc\space{%�\idx*\space�
               \csname impact@" "\endcsname
               \impact@i% puis va voir le prochain token
}
%
% lit l'argument suivant
\def\impact@arg#1{%
               \csname impact@% affiche
                       \ifcsname impact@"#1"\endcsname�\tidx{ifcsname}�
                               "#1"% le caract�re \impact@"#1" s'il est d�fini
                       \else
                               "error"% sinon \impact@"error"
                       \fi
               \endcsname
               \hskip\letter@skip% ins�rer le ressort inter-lettre�\idx*\hskip�
               \impact@i% puis, aller voir le prochain token
}
\def\impact@endprocess\impactend{% macro ex�cut� lorsqque le quark \impactend va �tre lu
               \unskip% annuler le dernier ressort�\idx*\unskip�
               \par% composer le paragraphe pour prendre en compte
                   % \baselineskip, \lineskip et \lineskiplimit
       \endgroup% et fermer le groupe
}
\catcode`\!=12 % rend le point d'exclamation "gentil"
\impact Programmer en {TEX} est facile et tr{e`}s utile !\impactend\par
\impact[2pt][0.5pt]Programmer en {TEX} est facile et tr{e`}s utile !\impactend��*\impact�|

La valeur de \idx\baselineskip s'explique par le fait que tels qu'ils sont dessin�s, les caract�res alphanum�riques de la police impact ont au maximum 9 pixels de \emph{hauteur totale}, o� la hauteur totale est la somme de la hauteur et de la profondeur. L'encombrement vertical maximal d'un caract�re est donc

\[9\times\verb|\pixelsize|+7\times\verb|\pixelsep|\]

Pour augmenter un peu l'espacement entre les lignes, on rajoute � cette dimension $3\times\verb|\pixelsize|$, ce qui donne la valeur de \idx\baselineskip choisie pour composer le paragraphe compos� en police impact.

\idx*[|)]{police Impact}

\section{Tracer des graphiques}
Pourquoi vouloir tracer un graphique avec \TeX{} alors que des extensions tr�s puissantes\footnote{Les deux plus connues sont PStricks et Ti\textit kz.} aux capacit�s quasi illimit�es existent pour cela ? Il s'agit ici non pas de les concurrencer, mais de relever le d�fi et exploiter les maigres possibilit�s qu'offre \TeX{}, c'est-�-dire les r�glures. Le but est de comprendre comment les placer pr�cis�ment dans une zone. Voici par exemple ce qu'il est possible de faire :

\begin{centrage}
       \xunit=1cm \yunit=0.75cm
       \def\fonction#1{\dimtodec\dimexpr\decmul{#1}{\decmul{#1}{#1}}pt-%
               \decmul{#1}{#1}pt-#1pt*3+2pt\relax}%
       \graphzone{-2}[0.5]{2.5}[5]{-5}{5}[2]{%
               \let\plotstuff\cross% d�finit ce qu'il faut afficher comme point
               \FOR\xx=-2 to 2.5 \do 0.1{%
                       \plot(\xx,\fonction{\xx})% afficher les points de coordonn�es (x ; f(x))
               }%
               \putat{5pt}{\dimexpr\graphboxht-10pt\relax}% afficher
                       {$\scriptstyle f(x)=x^3-x^2-3x+2$}% la fonction trac�e
               \showaxis% et les axes
       }%
\end{centrage}

Le nombre de r�glures est assez important et nous allons d�couper le probl�me en probl�mes �l�mentaires avant de rassembler le tout � la fin.

La m�thode qui va �tre notre fil directeur est de tracer \emph{toutes} les r�glures et \emph{tous} les caract�res apr�s avoir rendu leurs dimensions nulles. Ainsi, pendant tout le trac�, le \idx{point de r�f�rence} reste le point inf�rieur gauche qui a pour coordonn�es dans cet exemple \hbox{ $(-2{,}5\;\string;\;-5)$}. C'est seulement � la fin que l'on forcera une boite � prendre celle du graphique afin que la boite englobante\idx*{boite!englobante} du tout co�ncide avec le rectangle repr�sentant la zone graphique.

\subsection{Dessiner des axes gradu�s}\idx*[|(]{axe gradu�}
Le premier probl�me est de tracer les axes gradu�s situ�s en bas et � gauche de la zone. \Qu els param�tres faut-il sp�cifier pour tracer un axe horizontal tel que celui-ci ?

\begin{centrage}
\leavevmode\xaxis[2cm]{-2}[2]{8}[4]
\end{centrage}

Une simple observation permet de r�pondre. Il faut :

\begin{enumerate}
       \item l'abscisse de d�part et celle d'arriv�e �\verb|xmin|� et �\verb|xmax|� (ici $-2$ et $8$);
       \item l'incr�ment �\verb|inc|� entre 2 graduations principales (ici $2$);
       \item le nombre de subdivisions �\verb|nb_subdiv|� (ici $4$);
       \item la distance �\verb|dist|� entre deux graduations principales (ici \numprint[cm]2);
       \item enfin, les dimensions des r�glures proprement dites :\label{graphzone.non.arg}
       \begin{itemize}
               \item les dimensions verticales des traits repr�sentant une division principale et une subdivision ;
               \item les �paisseurs des traits repr�sentant une division principale et une subdivision ;
               \item l'�paisseur du trait horizontal repr�sentant l'axe.
       \end{itemize}
\end{enumerate}

Nous allons d�cider que la macro �\xaxis va tracer un axe horizontal et que tous les arguments (sauf ceux du point \no\ref{graphzone.non.arg}) seront pass�s � la macro. Celle-ci aura 5 arguments (2 obligatoires et 3 optionnels) dispos�s selon cette syntaxe :

\centrecode-\xaxis[dist]{xmin}[inc]{xmax}[nb_subdiv]-�*\xaxis

Les 5 autres dimensions graphiques du point \no\ref{graphzone.non.arg} seront contenues dans des registres de dimension :

\begin{itemize}
       \item \verb|\maingraddim| et \verb|\subgraddim| pour les hauteurs des traits ;
       \item \verb|\maingradwd| et \verb|\subgradwd| pour leurs �paisseurs;
       \item \verb|\axiswd| pour l'�paisseur de l'axe.
\end{itemize}

Maintenant que la syntaxe est d�finie, passons au m�canisme de trac� proprement dit. Voyons d'abord comment tracer une graduation principale avec une abscisse situ�e au-dessous. Pour le trait, nous utiliserons un \idx\rlap pour que sa dimension soit nulle. Pour le nombre affich� au-dessous, il sera l'argument de la macro et sera �galement affich� avec la macro �\clap, et abaiss� de \verb|1.5ex| � l'aide de la primitive \idx\lower :

\showcode/\newdimen\maingraddim \maingraddim=4pt % hauteur des graduations principales�\idx*\newdimen�
\newdimen\maingradwd \maingradwd=0.5pt % �paisseur des graduations principales
\def\maingradx#1{%
       \lower1.5ex\clap{$\scriptscriptstyle#1$}% afficher l'argument au dessous�\idx*\lower\idx*\scriptscriptstyle�*\clap�
       \clap{\vrule height\maingraddim width\maingradwd depth0pt }% et la r�glure�\idx*\rlap\idx*\vrule�
}
D�but\maingradx{1}suite\maingradx{2}conclusion\maingradx{3}fin./

La longueur horizontale de l'axe sera

\[\text{\small\tt dist}\times\frac{\text{\small\tt xmax}-\text{\small\tt xmin}}{\text{\small\tt inc}}\]

Voici donc une �bauche de la macro �\xaxis :

\showcode|\maingraddim=4pt \maingradwd=0.5pt
\newdimen\axiswd \axiswd=0.5pt �\idx*\newdimen�
\newmacro\xaxis[1cm]1[1]1[4]{%% #1= dist  #2=xmin  #3=inc  #4=xmax  #5=subdiv��*\xaxis�*\newmacro�
       \hbox{% mettre le tout dans une \hbox�\idx*\hbox�
               \rlap{% en d�bordement � droite :
                       \FOR\xx = #2 to #4 \do #3{% pour chaque graduation principale��*\FOR�
                               \maingradx{\xx}% tracer la graduation et �crire l'abscisse
                               \kern#1\relax% puis se d�placer vers la droite�\idx*\kern�
                       }%
               }%
               \vrule% tracer l'axe des abscisses�\idx*\vrule\defline\aaa�
                       height\axiswd% d'epaisseur \axiswd, de longueur #1*(#4-#2)/#3
                       width\dimexpr#1*\decdiv{\dimtodec\dimexpr#4pt-#2pt\relax}{#3}\relax��*\decdiv�*\dimtodec�
                       depth 0pt\relax % et de profondeur nulle�\defline\bbb�
       }%
}
a) \xaxis{-2}{5}suite

b) \frboxsep=0pt\frbox{\xaxis[1.25cm]{-1}[0.25]{1}}suite��*\axis�*\frboxsep�*\frbox�*\xaxis�|

Dans le deuxi�me cas, on constate en l'encadrant avec �\frbox que l'encombrement de l'axe est bon. C'est ce qui �tait recherch� puisque la seule chose trac�e ayant une dimension horizontale non nulle est l'axe lui-m�me, c'est-�-dire la \idx\vrule des lignes \nos\aaa-\bbb{}.

Il nous reste � ins�rer dans chaque boucle les graduations secondaires qui sont au nombre de \hbox{$\verb|#|5-1$}. Elles seront affich�es en d�bordement � droite apr�s chaque graduation principale, sauf pour la derni�re. Pr�alablement � la boucle, elles seront stock�es dans une \idx\hbox via le registre de boite \no0. Dans cette \idx\hbox, il doit y avoir $\verb|#5|-1$ fois ceci :

\begin{itemize}
       \item une espace de dimension \hbox{$\verb|#|1\div\verb|#|5$};
       \item une r�glure de dimension nulle correspondant � la marque de subdivision.
\end{itemize}

Nous avons le choix pour remplir cette \idx\hbox avec ces $\verb|#5|-1$ r�p�titions. Soit nous faisons appel � \idx\leaders, soit � une boucle �\for. C'est cette deuxi�me alternative qui sera choisie ici :

\showcode|\maingraddim=4pt \maingradwd=0.5pt \axiswd=0.5pt
\newdimen\subgraddim \subgraddim=2.5pt �\idx*\newdimen�
\newdimen\subgradwd \subgradwd=0.2pt
% trace un trait de subdivision
\def\subgradx{\clap{\vrule height\subgraddim width\subgradwd depth0pt }}�\idx*\rlap\idx*\vrule�

\newmacro\xaxis[1cm]1[1]1[4]{% #1= dist  #2=xmin  #3=inc  #4=xmax  #5=subdiv��*\xaxis�*\newmacro�
       \hbox{% tout mettre dans une \hbox�\idx*\hbox�
               \setbox0=\hbox{% stocke dans une \hbox les grad secondaires entre 2 unit�s�\idx*\setbox�
                       \edef\dimsubgrad{\the\dimexpr#1/#5\relax}% dimension entre 2 subdivisions�\idx*\the�
                       \for\xx=1 to #5-1 \do{% ins�rer #5-1 fois��*\for�
                               \kern\dimsubgrad% une espace secondaire�\idx*\kern�
                               \subgradx% une graduation secondaire
                               }%
               }%
               \rlap{% en d�bordement � droite :
                       \FOR\xx = #2 to #4 \do #3{% pour chaque graduation principale��*\FOR�
                               \maingradx{\xx}% imprimer l'abscisse
                               \ifdim\xx pt<#4pt % et en d�bordement � droite,
                                       \rlap{\copy0 }% les r�glures secondaires, sauf pour la derni�re�\idx*\rlap\idx*\copy�
                               \fi
                               \kern#1\relax% se d�placer vers la droite�\idx*\kern�
                       }%
               }%
               \vrule% tracer l'axe des abscisses�\idx*\vrule\defline\aaa�
                       height\axiswd% d'epaisseur \axiswd, de longueur #1*(#4-#2)/#3
                       width\dimexpr#1*\decdiv{\dimtodec\dimexpr#4pt-#2pt\relax}{#3}\relax��*\decdiv�*\dimtodec�
                       depth 0pt\relax % et de profondeur nulle�\defline\bbb�
       }%
}
a) \xaxis{-2}{5}[2]

)b \xaxis[1.25cm]{-1}[0.25]{1}[5]�\idx*\leavevmode�*\xaxis�|

Retenons que la largeur de la \idx\hbox chapeau est la largeur de la zone graphique. Notons �galement que l'on \emph{ne peut pas} �crire

\centrecode|\setbox0\xaxis{-2}{5}[2]|�*\axis

\noindent car, contrairement aux apparences, la macro �\xaxis ne se d�veloppe pas en une \idx\hbox. Cela est d� � la fa�on dont �\newmacro construit les macros qui ont des arguments optionnels : des sous-macros sont cr��es et l'emploi de \idx\futurelet annule toute possibilit� de d�veloppement maximal.

Passons maintenant aux axes verticaux. La m�thode va �tre la m�me, sauf que toutes les primitives typ�es en mode horizontal\idx*{mode!horizontal} passeront cette fois en mode vertical\idx*{mode!vertical} : nous mettrons le tout dans une \idx\vbox et puisqu'elle sera remplie du haut vers le bas, il faudra commencer avec l'ordonn�e de fin et construire une boucle �\FOR avec un incr�ment n�gatif.

La m�thode utilis�e avec �\yaxis pour l'affichage des ordonn�es ne sera pas identiques � celles des abscisses : les dimensions des nombres repr�sentant les ordonn�es seront rendues nulles gr�ce � une \idx\llap. En effet, la dimension horizontale d'un nombre est variable alors que sa dimension verticale est constante. R�server suffisamment d'espace � gauche de l'axe pour y placer les ordonn�es aurait n�cessit� de calculer la plus grande dimension horizontale des ordonn�es ce qui implique une boucle pr�alable. Il s'av�re donc plus facile et plus �conomique d'ignorer cette dimension horizontale, quitte � rejeter hors de la boite englobante toutes les ordonn�es.

\showcode|\maingraddim=4pt \maingradwd=0.5pt \axiswd=0.5pt
\subgraddim=2.5pt \subgradwd=0.2pt
\def\maingrady#1{% affiche...
       \vlap{\llap{$\scriptscriptstyle#1$\kern2pt }}% l'ordonn�e...��*\vlap \idx*\llap\idx*\scriptscriptstyle�
       \vbox to0pt{\vss\hrule height\maingradwd width\maingraddim depth0pt }% et la r�glure�\idx*\vbox\idx*\vss\idx*\hrule�
}

% affiche une subdiv
\def\subgrady{\vlap{\hrule height\subgradwd width\subgraddim depth0pt }}��*\vlap\idx*\hrule�
\newmacro\yaxis[1cm]1[1]1[4]{%
% #1= dist  #2=ymin  #3=inc  #4=ymax  #5=subdiv��*\yaxis�*\newmacro�
       \vbox{%�\idx*\vbox�
               \offinterlineskip% d�sactiver le ressort d'interligne�\idx*\offinterlineskip�
               \setbox0=\vbox{% stocke dans une \hbox les grad secondaires entre 2 unit�s�\idx*\setbox�
                       \edef\dimsubgrad{\the\dimexpr#1/#5\relax}% dimension entre 2 subdivisions�\idx*\the�
                       \for\xx=1 to #5-1 \do{% ins�rer #5-1 fois��*\for�
                               \kern\dimsubgrad% une espace secondaire�\idx*\kern�
                               \subgrady% une graduation secondaire
                               }%
               }%
               \edef\dimsubgrad{\the\dimexpr#1/#5\relax}% distance entre 2 subdivisions�\idx*\the\idx*\dimexpr�
               \vbox to 0pt{% en d�bordement vers le bas
                       \FOR\xx = #4to#2\do-#3{%��*\FOR�
                               \maingrady{\xx}% imprimer l'abscisse
                               \ifdim\xx pt>#2pt % et en d�bordement � droite,
                                       \vbox to 0pt{\copy0 \vss}% les r�glures secondaires, sauf pour la derni�re�\idx*\copy\idx*\vss�
                               \fi
                               \kern#1\relax% se d�placer vers la droite�\idx*\kern�
                       }%
                       \vss% assure le d�bordement vers le bas�\idx*\vss�
               }%
               \clap{\vrule% tracer l'axe des ordonn�es
                       width\axiswd% d'�paisseur \axiwd, et de hauteur (#4-#2)/#3*#1
                       height\decdiv{\dimtodec\dimexpr(#4pt-#2pt)\relax}{#3}\dimexpr#1\relax��*\decdiv�*\dimtodec�
                       depth 0pt\relax % profondeur nulle
               }%
       }%
}

Essai : \yaxis{-2}{5}[2]\qquad \frboxsep=0pt \frbox{\yaxis[0.75cm]{-1}[0.5]{3}[5]}��*\frboxsep�*\frbox�*\yaxis�|\idx*[|)]{axe gradu�}

\subsection{Cr�er une zone pour le graphique}
Tout est maintenant pr�t pour tracer notre zone graphique. Deux registres de dimension suppl�mentaires vont �tre cr��s, \verb|\xunit| et \verb|\yunit|, chacun sp�cifiant la distance entre deux graduations principales sur chacun des axes. La syntaxe de la macro va �tre proche des syntaxes de �\xaxis ou �\yaxis:

\centrecode-\graphzone{xmin}[xinc]{xmax}[nbsubdivx]{ymin}[yinc]{ymax}[nbsubdivy]{<code>}-�*\graphzone

\noindent o� le \verb|<code>| contient les instructions graphiques que nous verrons plus tard et qui permettent de dessiner dans la zone.

\showcode|\newdimen\xunit \xunit=1cm �\idx*\newdimen�
\newdimen\yunit \yunit=0.75cm
\maingraddim=4pt \maingradwd=0.5pt \axiswd=0.5pt
\subgraddim=2.5pt \subgradwd=0.2pt
\catcode`@11
\newmacro\graphzone1[1]1[4]1[1]1[4]{%��*\graphzone�*\newmacro�
       \leavevmode% quitter le mode vertical�\idx*\leavevmode\idx*{mode!vertical}�
       \begingroup% travailler dans un groupe semi-simple
               \def\graphxmin{#1}\def\graphxmax{#3}% sauvegarder
               \def\graphymin{#5}\def\graphymax{#7}% les
               \def\xincrement{#2}\def\yincrement{#6}% arguments
               \setbox0\hbox{\yaxis[\yunit]{#5}[#6]{#7}[#8]}% axe "y" dans boite 0�\idx*\setbox�*\yaxis�
               \setbox1\hbox{\xaxis[\xunit]{#1}[#2]{#3}[#4]}% axe "x" dans boite 1�\idx*\setbox�*\xaxis�
               \edef\graphboxht{\the\ht0 }% \graphboxh est la hauteur de la zone�\idx*\the\idx*\ht�
               \edef\graphboxwd{\the\wd1 }% \graphboxw est la largeur de la zone�\idx*\wd�
               \rlap{% annuler la dimension horizontale, et...�\idx*\rlap�
                       \box1 % ...afficher l'axe (Ox) puis�\idx*\box�
                       % le trait vertical � l'extr�me droite de la zone
                       \clap{\vrule height\dimexpr\graphboxht+\axiswd\relax width\axiswd depth0pt }%�\idx*\vrule\idx*\dimexpr�
                       }%
               \rlap{\box0 }% afficher l'axe (Oy) en annulant sa dimension horizontale�\idx*\rlap\idx*\box�
               \raise\graphboxht% puis monter tout en haut de la zone�\idx*\raise�
                       % pour tracer le trait horizontal en annulant sa longueur
                       \rlap{\kern-0.5\axiswd% et en rattrapant le centrage de l'axe des ordonn�es
                               \vrule height\axiswd width\dimexpr\graphboxwd+\axiswd}%�\idx*\rlap\idx*\vrule�
               \begingroup% pour lire l'argument "<code>" :
                       \catcode`\^^M=9\relax % ignorer les retours � la ligne�\verbidx*[ (retour charriot)]{^^M}�
                       \graphzone@i% appeler \graphzone@i
}
\def\graphzone@i#1{% lire le <code>...
               \endgroup% et fermer le groupe pr�c�demment ouvert
               \setbox0\hbox{#1}% mettre les instructions graphique dans la boite 0�\idx*\setbox�
               \wd0=\dimexpr\graphboxwd+\axiswd\relax% forcer sa dim horizontale�\idx*\wd\idx*\dimexpr�
               \ht0=\dimexpr\graphboxht+\axiswd\relax% et verticale�\idx*\ht�
               % pour correspondre aux dimension de la zone graphique
               \box0 % l'afficher�\idx*\box\defline\aaa�
       \endgroup% sortir du groupe initial
}
\catcode`@12
essai\graphzone{-1}[0.5]{1.5}[5]{-20}[10]{10}[2]{\relax}fin��*\graphzone�|

Le code ne pr�sente pas beaucoup de difficult�. Signalons tout de m�me les quelques points suivants:
\begin{itemize}
       \item les r�glures correspondant au trait vertical � droite et au trait horizontal en haut sont trac�es � coup de \idx\vrule. Celle de droite est trac�e � la suite de \idx\box\verb|1| qui est l'axe horizontal et celle du haut en est correctement plac�e en s'aidant de \idx\raise qui �l�ve la boite \idx\rlap de la hauteur de la zone graphique ;
       \item on a modifi� le code de cat�gorie du retour � la ligne dans l'argument final \verb|<code>| de �\graphzone afin que les instructions graphiques puissent �tre entr�es le plus � naturellement � possible, notamment sans avoir besoin de commenter les fins de ligne ;
       \item le \idx{point de r�f�rence} demeure en bas � gauche de la zone graphique jusqu'au \idx\box\verb|0| de la macro \verb|\graphzone@i| (ligne \no\aaa{}) puisque jusque l�, on n'a affich� que des \idx\rlap. C'est justement en for�ant les dimensions de cette boite \no0 aux dimensions de la zone graphique qu'en l'affichant, on obtient le bon encombrement final.
\end{itemize}

\subsection{Remplir la zone graphique}
Il nous reste � �crire des instructions graphiques pour remplir la zone\ldots{} Tout d'abord, il va falloir construire une macro �\putat qui place n'importe quel contenu relativement au \idx{point de r�f�rence} courant :

\centrecode-\putat{dimx}{dimy}{<contenu>}-�*\putat

Il est bien entendu que cette macro va placer le point de r�f�rence du \verb|<contenu>| � des coordonn�es relatives par rapport au point de r�f�rence courant, mais \emph{sans changer ce \idx{point de r�f�rence} courant}. Autrement dit, la boite englobante\idx*{boite!englobante} de cette macro a toutes ses dimensions nulles et donc, son ex�cution n'a aucune influence sur le point de r�f�rence courant.

En jouant sur les boites et imbriquant des boites horizontales et verticales en d�bordement, on peut facilement effectuer cette action :

\showcode|\def\putat#1#2#3{%��*\putat�
       \leavevmode\rlap{\kern#1\vbox to0pt{\vss\hbox{#3}\kern#2}}%�\idx*\leavevmode\idx*\rlap\idx*\kern\idx*\vbox\idx*\hss�
}
Essai\putat{0.5cm}{0.3cm}{A}\putat{-0.2cm}{-0.1cm}{B}\putat{0pt}{0.2cm}{C}suite��*\putat�|

Cette macro �\putat va nous permettre de placer n'importe quel mat�riel dans la zone graphique, mais l'id�al serait que le mat�riel plac� le soit avec les coordonn�es affich�es sur les bords de la zone graphique (que nous appelons $X$ et $Y$) et non pas les coordonn�es par rapport au coin inf�rieur gauche ($x$ et $y$) qui est le \idx{point de r�f�rence}. Il est bien entendu facile de passer d'un syst�me de coordonn�es � l'autre avec une simple formule de changement de rep�re :

\[\begin{cases}
       X=(x-x_{\text{min}})\div x_{\text{inc}}\\[5pt]
       Y=(y-y_{\text{min}})\div y_{\text{inc}}
\end{cases}\]

Pour �viter que les divisions ne soient faites � chaque placement d'un objet, nous diviserons une bonne fois pour toutes les dimensions \verb|\xunit| et \verb|\yunit| par les incr�ments $x_{\text{inc}}$ et $y_{\text{inc}}$ � l'int�rieur de la zone graphique.

Pour placer les axes, il faut d'abord tester si le nombre 0 est contenu dans l'intervalle repr�sent� sur l'axe horizontal dans la zone graphique et faire de m�me pour l'axe vertical. Le plus simple est de modifier la macro �\ifinside, programm�e � la page~\pageref{ifinside}, mais qui avait le d�faut de n'agir que sur les entiers :

\showcode|\def\ifinside#1[#2,#3]{%��*\ifinside�
       \ifnum\sgn{\dimexpr#1pt-#2pt\relax}\sgn{\dimexpr#1pt-#3pt}1=1 ��*\sgn�
               \expandafter\secondoftwo
       \else
               \expandafter\firstoftwo
       \fi
}
1) \ifinside3.5[0.5,4]{vrai}{faux}\qquad
2) \ifinside-0.2[-0.4,-0.3]{vrai}{faux}\qquad
3) \ifinside-0.999[-1,-0.5]{vrai}{faux}��*\ifinside�|

Puis, il faut d�finir la fonction dont on veut afficher la courbe repr�sentative, sachant que les seules op�rations dont nous disposons sont les quatre op�rations arithm�tiques sur des d�cimaux. On ne peut donc repr�senter que des fonctions rationnelles\footnote{Il est bien �vident qu'avec une extension sp�cialis�e dans le calcul comme l'est �\texttt{fp}�, toutes les fonctions, y compris transcendantes, sont tr�s facilement accessibles.}.

Supposons que l'on veuille repr�senter la fonction $f(x)=x^3-x^2-3x+2$. Nous allons devoir faire le petit effort de traduire cet enchainement d'op�rations en instructions compr�hensibles par \eTeX{} muni des macros rendant possibles la multiplication et la division par un d�cimal que sont �\decmul et �\decdiv, vues � partir de la page~\pageref{decmul} :

\showcode|\def\fonction#1{\dimtodec\dimexpr��*\dimtodec�
       \decmul{#1}{\decmul{#1}{#1}}pt% x^3��*\decmul�
       -\decmul{#1}{#1}pt% -x^2��*\decmul�
       -#1pt*3% -3x
       +2pt\relax}% +2
1) \fonction{-4}\qquad% doit afficher -66
2) \fonction{-1.7}\qquad %  doit afficher -0.703
3) \fonction{1}\qquad%  doit afficher -1
4) \fonction{1.35}%  doit afficher -1.412125|

On voit ici que l'on a ajout� les dimensions en \idx*{unit�!pt}\idx*{pt (unit�)}\verb|pt| pour permettre � \idx\dimexpr d'effectuer le calcul avant que �\dimtodec n'enl�ve cette unit� pour que cette macro, purement d�veloppable, renvoie un nombre d�cimal sans unit�. Bien s�r, certaines erreurs d'arrondis rendent les r�sultats l�g�rement faux ce qui n'a aucune importance ici puisqu'ils seront des coordonn�es de points dans un rep�re o� l'erreur commise est insignifiante en regard de ce qui est visible � l'\oe il nu.

Il faut ensuite d�finir la forme du point qui sera affich�. Pourquoi pas une croix ? Il faut bien s�r qu'elle soit de dimensions nulles :

\showcode|\newmacro\cross[2pt][0.2pt]{%��*\cross�*\newmacro�
       % #1=dimensions de traits depuis le centre de la croix
       % #2=�paisseur des traits
       \leavevmode�\idx*\leavevmode�
       \vlap{%��*\vlap�
               \clap{%��*\clap�
                       \vrule height#2 depth0pt width#1 % 1/2 trait horizontal gauche
                       \vrule height#1 depth#1 width#2  % trait vertical
                       \vrule height#2 depth0pt width#1 % 1/2 trait horizontal droit
               }%�\idx*\vrule�
       }%
}
Une croix : \cross{}puis une autre\cross[8pt][0.8pt]��*\cross�|

Voici maintenant le code reprenant toutes les macros vues pr�c�demment o� deux courbes repr�sentatives sont construites :

\showcode|\maingraddim=4pt \maingradwd=0.5pt \axiswd=0.5pt
\subgraddim=2.5pt \subgradwd=0.2pt
\xunit=1.25cm \yunit=0.75cm

\def\maingradx#1{%
       \lower1.5ex\clap{$\scriptscriptstyle#1$}% afficher l'argument au dessous�\idx*\lower\idx*\scriptscriptstyle�*\clap�
       \clap{\vrule height\maingraddim width\maingradwd depth0pt }% et la r�glure�\idx*\rlap\idx*\vrule�
}

\def\subgradx{\clap{\vrule height\subgraddim width\subgradwd depth0pt }}�\idx*\rlap\idx*\vrule�

\newmacro\xaxis[1cm]1[1]1[4]{%��*\xaxis�*\newmacro�
       \hbox{% tout mettre dans une \hbox�\idx*\hbox�
               \setbox0=\hbox{% stocke dans une \hbox les grad secondaires entre 2 unit�s�\idx*\setbox�
                       \edef\dimsubgrad{\the\dimexpr#1/#5\relax}% dimension entre 2 subdivisions�\idx*\the�
                       \for\xx=1 to #5-1 \do{% ins�rer #5-1 fois��*\for�
                               \kern\dimsubgrad% une espace secondaire�\idx*\kern�
                               \subgradx% une graduation secondaire
                               }%
               }%
               \rlap{% en d�bordement � droite :
                       \FOR\xx = #2 to #4 \do #3{% pour chaque graduation principale��*\FOR�
                               \maingradx{\xx}% imprimer l'abscisse
                               \ifdim\xx pt<#4pt % et en d�bordement � droite,
                                       \rlap{\copy0 }% les r�glures secondaires, sauf pour la derni�re�\idx*\rlap\idx*\copy�
                               \fi
                               \kern#1\relax% se d�placer vers la droite�\idx*\kern�
                       }%
               }%
               \vrule% tracer l'axe des abscisses�\idx*\vrule\defline\aaa�
                       height\axiswd% d'epaisseur \axiswd, de longueur #1*(#4-#2)/#3
                       width\dimexpr#1*\decdiv{\dimtodec\dimexpr#4pt-#2pt\relax}{#3}\relax��*\decdiv�*\dimtodec�
                       depth 0pt\relax % et de profondeur nulle�\defline\bbb�
       }%
}

\def\maingrady#1{% affiche...
       \vlap{\llap{$\scriptscriptstyle#1$\kern2pt }}% l'ordonn�e...��*\vlap \idx*\llap\idx*\scriptscriptstyle�
       \vbox to0pt{\vss\hrule height\maingradwd width\maingraddim depth0pt }% et la r�glure�\idx*\vbox\idx*\vss\idx*\hrule�
}

% affiche une subdiv
\def\subgrady{\vlap{\hrule height\subgradwd width\subgraddim depth0pt }}��*\vlap\idx*\hrule�
% #1= dim entre 2 grad principales #2=abscisse d�part #3=incr�ment
% #4=abscisse arriv�e #5=nb intervalles secondaires
\newmacro\yaxis[1cm]1[1]1[4]{%��*\yaxis�*\newmacro�
       \vbox{%�\idx*\vbox�
               \offinterlineskip% d�sactiver le ressort d'interligne�\idx*\offinterlineskip�
               \setbox0=\vbox{% stocke dans une \hbox les grad secondaires entre 2 unit�s�\idx*\setbox�
                       \edef\dimsubgrad{\the\dimexpr#1/#5\relax}% dimension entre 2 subdivisions�\idx*\the�
                       \for\xx=1 to #5-1 \do{% ins�rer #5-1 fois��*\for�
                               \kern\dimsubgrad% une espace secondaire�\idx*\kern�
                               \subgrady% une graduation secondaire
                               }%
               }%
               \edef\dimsubgrad{\the\dimexpr#1/#5\relax}% distance entre 2 subdivisions�\idx*\the\idx*\dimexpr�
               \vbox to 0pt{% en d�bordement vers le bas
                       \FOR\xx = #4to#2\do-#3{%��*\FOR�
                               \maingrady{\xx}% imprimer l'abscisse
                               \ifdim\xx pt>#2pt % et en d�bordement � droite,
                                       \vbox to 0pt{\copy0 \vss}% les r�glures secondaires, sauf pour la derni�re�\idx*\copy\idx*\vss�
                               \fi
                               \kern#1\relax% se d�placer vers la droite�\idx*\kern�
                       }%
                       \vss% assure le d�bordement vers le bas�\idx*\vss�
               }%
               \clap{\vrule% tracer l'axe des ordonn�es
                       width\axiswd% d'�paisseur \axiwd, et de hauteur (#4-#2)/#3*#1
                       height\decdiv{\dimtodec\dimexpr(#4pt-#2pt)\relax}{#3}\dimexpr#1\relax��*\decdiv�*\dimtodec�
                       depth 0pt\relax % profondeur nulle
               }%
       }%
}

\catcode`@11
\newmacro\graphzone1[1]1[4]1[1]1[4]{%��*\graphzone�*\newmacro�
       \leavevmode% quitter le mode vertical�\idx*\leavevmode\idx*{mode!vertical}�
       \begingroup% travailler dans un groupe semi-simple
               \def\graphxmin{#1}\def\graphxmax{#3}% sauvegarder
               \def\graphymin{#5}\def\graphymax{#7}% les
               \def\xincrement{#2}\def\yincrement{#6}% arguments
               \setbox0\hbox{\yaxis[\yunit]{#5}[#6]{#7}[#8]}% axe "y" dans boite 0�\idx*\setbox�*\yaxis�
               \setbox1\hbox{\xaxis[\xunit]{#1}[#2]{#3}[#4]}% axe "x" dans boite 1�\idx*\setbox�*\xaxis�
               \edef\graphboxht{\the\ht0 }% \graphboxh est la hauteur de la zone�\idx*\the\idx*\ht�
               \edef\graphboxwd{\the\wd1 }% \graphboxw est la largeur de la zone�\idx*\wd�
               \rlap{% annuler la dimension horizontale, et...�\idx*\rlap�
                       \box1 % ...afficher l'axe (Ox) puis�\idx*\box�
                       % le trait vertical � l'extr�me droite de la zone
                       \clap{\vrule height\dimexpr\graphboxht+\axiswd\relax width\axiswd depth0pt }%�\idx*\vrule\idx*\dimexpr�
                       }%
               \rlap{\box0 }% afficher l'axe (Oy) en annulant sa dimension horizontale�\idx*\rlap\idx*\box�
               \raise\graphboxht% puis monter tout en haut de la zone�\idx*\raise�
                       % pour tracer le trait horizontal en annulant sa longueur
                       \rlap{\kern-0.5\axiswd% et en rattrapant le centrage de l'axe des ordonn�es
                               \vrule height\axiswd width\dimexpr\graphboxwd+\axiswd}%�\idx*\rlap\idx*\vrule�
               \begingroup% pour lire l'argument "<code>" :
                       \catcode`\^^M=9\relax % ignorer les retours � la ligne�\verbidx*[ (retour charriot)]{^^M}�
                       \graphzone@i% appeler \graphzone@i
}
\def\graphzone@i#1{% lire le <code>...
               \endgroup% et fermer le groupe pr�c�demment ouvert
               \xunit=\decdiv1\xincrement\xunit% divise les unit�s par l'incr�ment
               \yunit=\decdiv1\yincrement\yunit
               \setbox0\hbox{#1}% mettre les instructions graphique dans la boite 0�\idx*\setbox�
               \wd0=\dimexpr\graphboxwd+\axiswd\relax% forcer sa dim horizontale�\idx*\wd\idx*\dimexpr�
               \ht0=\dimexpr\graphboxht+\axiswd\relax% et verticale�\idx*\ht�
               % pour correspondre aux dimension de la zone graphique
               \box0 % l'afficher�\idx*\box\defline\aaa�
       \endgroup% sortir du groupe initial
}

\def\putat#1#2#3{%��*\putat�
       \leavevmode\rlap{\kern#1\vbox to0pt{\vss\hbox{#3}\kern#2}}%�\idx*\leavevmode\idx*\rlap\idx*\kern\idx*\vbox\idx*\hss�
}

\newmacro\cross[2pt][0.2pt]{%��*\cross�*\newmacro�
       \leavevmode�\idx*\leavevmode�
       \vlap{%��*\vlap�
               \clap{%��*\clap�
                       \vrule height#2 depth0pt width#1 % 1/2 terait horizontal gauche
                       \vrule height#1 depth#1 width#2  % trait vertical
                       \vrule height#2 depth0pt width#1 % 1/2 trait horizontal droit
               }%�\idx*\vrule�
       }%
}

\def\plot(#1,#2){% place "\plotstuff" aux coordonn�es #1,#2��*\plot�
       \edef\x@plot{#1}\edef\y@plot{#2}% d�velopper au cas o�
       \ifinside\x@plot[\graphxmin,\graphxmax]% si #1 est dans les limites��*\ifinside�
               {\ifinside\y@plot[\graphymin,\graphymax]% et si #2 l'est aussi��*\ifinside�
                       {\putat% placer aux coordonn�es��*\putat�
                               {\dimexpr\x@plot\xunit-\graphxmin\xunit\relax}% X=(x-xmin)/xinc�\idx*\dimexpr�
                               {\dimexpr\y@plot\yunit-\graphymin\yunit\relax}% Y=(y-ymin)/yinc�\idx*\dimexpr�
                               \plotstuff% le contenu de \plotstuff
                       }%
                       \relax
               }
               \relax
}

\def\showxaxis{% affiche l'axe (Ox)
       \ifinside0[\graphymin,\graphymax]%��*\ifinside�
               {\putat\z@{-\graphymin\yunit}{\vlap{\vrule width\graphboxwd height\axiswd}}}%�\idx*\vrule �*\putat\idx*\z@�
               \relax
}

\def\showyaxis{% affiche l'axe (Oy)
       \ifinside0[\graphxmin,\graphxmax]%��*\ifinside�
               {\putat{-\graphxmin\xunit}\z@{\clap{\vrule width\axiswd height\graphboxht}}}%�\idx*\vrule �*\putat\idx*\z@�
               \relax
}

\def\showaxis{\showxaxis\showyaxis}% affiche les deux axes
\catcode`@12

%%%%%%%%%%%%%%% 1er exemple :
\xunit=1cm \yunit=0.5cm
\def\fonction#1{\dimtodec\dimexpr\decmul{#1}{\decmul{#1}{#1}}pt-%
       \decmul{#1}{#1}pt-#1pt*3+2pt\relax}��*\dimtodec �*\decmul\idx*\dimexpr�
Exemple 1 :\qquad
\graphzone{-2}[0.5]{2.5}[5]{-5}{5}[2]{%��*\graphzone�
       \let\plotstuff\cross% d�finit ce qu'il faut afficher comme point��*\cross�
       \FOR\xx=-2 to 2.5 \do 0.1{%��*\FOR�
               \plot(\xx,\fonction{\xx})% afficher les points de coordonn�es (x ; f(x))��*\plot�
       }%
       \putat{5pt}{\dimexpr\graphboxht-10pt\relax}% afficher��*\putat�
               {$f(x)=x^3-x^2-3x+2$}% la fonction trac�e
       \showaxis% et les axes
}\par\medskip�\idx*\medskip�
%%%%%%%%%%%%% 2e exemple
\xunit=0.7cm \yunit=\xunit
\def\foncx#1{\dimtodec\dimexpr\decmul{#1}{\decmul{#1}{#1}}pt-%
       \decmul{4}{\decmul{#1}{#1}}pt-#1pt+4pt}��*\dimtodec �*\decmul\idx*\dimexpr�
\def\foncy#1{\dimtodec\dimexpr\decmul{#1}{#1}pt-#1pt*2-6pt}��*\dimtodec �*\decmul\idx*\dimexpr�
Exemple 2 :\qquad
\graphzone{-12}[2]{12}[2]{-8}[2]{8}[2]{%��*\graphzone�
       \def\plotstuff{\cross[1.25pt]}��*\cross�
       \FOR\tt = -5 to 5 \do 0.1 {%��*\FOR�
               \plot(\foncx\tt,\foncy\tt)%��*\plot�
       }%
       \putat{5pt}{\dimexpr\graphboxht-20pt\relax}% afficher la fonction param�trique trac�e��*\putat�
               {$\left\{\vcenter{\hbox{$x(t)=t^3-4t^2-t-4$}\hbox{$y(t)=t^2-2t-6$}}\right.$}%�\idx*\vcenter�
       \showaxis
}|

\subsection{Construire l'ensemble de Mandelbrot}\idx*{Mandelbrot}
L'\idx{ensemble de Mandelbrot}\footnote{Du nom de son inventeur, Beno�t \textsc{Mandelbrot} (1924--2010), math�maticien franco-arm�nien.}, not� $\mathcal M$, est une figure fractale d�finie comme l'ensemble des points $c$ du plan complexe pour lesquels la suite d�finie par r�currence par

\[\left\{
\begin{tabular}{@{}r@{}l}
$z_0$&${}=0$\\[2ex]
$z_{n+1}$&${}=z_n^2+c$
\end{tabular}
\right.\]

\noindent est born�e en module. En posant $c=a+\mathrm ib$, on passe aux coordonn�es cart�siennes et l'on obtient

\[\left\{
\begin{tabular}{@{}r@{}l}
$x_0$&${}=0$\\[2ex]
$x_{n+1}$&${}=x_n^2-y_n^2+a$
\end{tabular}\right.\kern5em
\left\{\begin{tabular}{@{}r@{}l}
$y_0$&${}=0$\\[2ex]
$y_{n+1}$&${}=2x_n y_n+b$
\end{tabular}
\right.\]

Cet ensemble a �t� beaucoup �tudi� et on a d�montr� les choses suivantes qui vont nous servir pour le construire :

\begin{itemize}
       \item $\mathcal M$ est sym�trique par rapport � l'axe des abscisses et donc, on peut se limiter au calcul des points dont la partie imaginaire est positive et tracer leurs sym�triques par rapport � $(Ox)$;
       \item si � un certain indice $i$, on a $|z_i|>2$, alors la suite diverge et donc, le point d'affixe $c$ n'appartient pas � $\mathcal M$. Il est d�s lors inutile de poursuivre les calculs aux indices sup�rieurs � $i$.
\end{itemize}

Pour dessiner l'ensemble, nous nous limiterons � la portion de plan complexe comprise entre $-2$ et $1$ pour la partie r�elle et entre $-1$ et $1$ pour la partie imaginaire. L'essentiel est d'�crire une macro �\mandeltest qui admet deux arguments d�cimaux qui sont les coordonn�es du point � tester. Cette macro mettra en place une boucle qui calculera les termes de la suite en fonction des deux arguments qui repr�sentent $Re(c)$ et $Im(c)$. Bien �videmment, si la suite ne diverge pas, il n'est pas possible de calculer un nombre illimit� de termes de la s�rie. Nous nous limiterons � un entier, contenu dans la macro \verb|\maxiter|.

L'algorithme de �\mandeltest est tr�s simple : les it�rations doivent se poursuivre tant que le nombre d'it�rations est inf�rieur � \verb|\maxiter| et que le module du terme $z_i$ actuellement calcul� est inf�rieur � 2. Une fois le test termin� et l'issue connue, le test �\mandeltest d�finira la macro \verb|\mandelresult|  : elle contiendra 1 si le test est positif et 0 sinon.

Pour chaque terme $z_i$, les macros \verb|\zx| et \verb|\zy| contiennent $Re(z_i)$ et $Im(z_i)$. Par souci d'optimisation et pour ne pas les calculer deux fois, nous stockerons les carr�s de \verb|\zx| et \verb|\zy| dans \verb|\zxx| et \verb|\zyy|.

\begingroup
\numalgofalse
\def\algoleftskip{.1\hsize}
\def\algorightskip{.1\hsize}\label{algo3}
\algorithm[\#]{Tester si un point appartient � M}/
macro ~mandeltest~ #1#2 % #1 et #2 = coordonn�es du point � tester
       mandelresult:=1 % on consid�re a priori que le point apprtient � M
       zx:=0 \qquad  zy:=0 % partie r�elle et imaginaire de $z_0$
       zxx:=0\qquad zyy:=0 % les carr�s de zx et zy
       ~pour~ i=1 to maxiter
               zy:=2*zx*zy + #2 % $y_{n+1}=2x_n y_n + Im(c)$
               zx:=zxx-zyy + #1 % $x_{n+1}=x_n^2-y_n^2+Re(c)$
               zxx:=zx*zx\qquad zyy:=zy*zy % calcul des carr�s
               ~si~ $\mathrm{zxx}+\mathrm{zyy}>4$ % si $|z_n|^2>4$ (c�d si le module est > � 2)
                       mandelresult:=0 % le point n'est pas dans M
                       i:=maxiter % sortir de la boucle pr�matur�ment
               ~finsi~
       ~finpour~
~finmacro~/
\endgroup

Dans le domaine $[-2\;\string;\;1]\times[-1\;\string;\;1]$ nous allons choisir la \emph{r�solution} du dessin, c'est-�-dire combien de pixels doivent �tre contenus dans une unit�, aussi bien horizontalement que verticalement. Ce nombre sera le premier argument de la macro �\mandel charg�e de tracer $\mathcal M$. Le second argument sera le nombre maximal d'it�rations.

Pour parcourir tous les points du rectangle, nous allons utiliser deux boucles �\FOR imbriqu�es, l'une pilotant les abscisses \verb|\xxx| et l'autre les ordonn�es \verb|\yyy|. L'incr�ment sera �gal � $\frac{1}{\string#1}$. Dans le c\oe ur de la boucle, c'est-�-dire pour chaque point de coordonn�es (\verb|\xxx|\;\string;\;\verb|\yyy|), le test �\mandeltest sera effectu� et si la macro \verb|\mandelresult| vaut 1, le pixel et son sym�trique par rapport � l'axe $(Ox)$ seront affich�s.

Un pixel sera une r�glure carr�e ayant pour c�t� l'incr�ment multipli� par la longueur \verb|\xunit|.

\errcode|\def\mandeltest#1#2{%��\mandeltest�
       \def\zx{0}\def\zy{0}% zn=0 + i*0
       \def\zxx{0}\def\zyy{0}% carr�s de \zx et \zy
       \def\mandelresult{1}% le point appartient � M a priori
       \for\ii=1to\maxiter\do1{%��*\for�
               \advance\count255 by1�\idx*\advance�
               \edef\zy{\dimtodec\dimexpr\decmul{\decmul2\zx}\zy pt+#2pt\relax}%��*\dimtodec\idx*\dimexpr �*\decmul�
               \edef\zx{\dimtodec\dimexpr\zxx pt-\zyy pt+#1pt\relax}%%��*\dimtodec\idx*\dimexpr�
               \edef\zxx{\decmul\zx\zx}%��*\decmul�
               \edef\zyy{\decmul\zy\zy}%��*\decmul�
               \ifdim\dimexpr\zxx pt+\zyy pt\relax>4pt�\tidx*{ifdim}�
                       \def\mandelresult{0}%
                       \exitfor\ii��*\exitfor�
               \fi
       }%
}
\def\mandel#1#2{% #1=points par unit� #2=nombre maximal d'it�rations��\mandel�
       \graphzone{-2}[1]{1}[2]{-1}[1]{1}[2]{%��*\graphzone�
               \def\maxiter{#2}%
               \edef\plotstuff{\the\dimexpr\xunit/#1\relax}% taille d'un pixel�\idx*\the\idx*\dimexpr�
               \edef\plotstuff{\vrule height\plotstuff width\plotstuff}%�\idx*\vrule�
               \edef\increment{\decdiv{1}{#1}}% incr�ment��*\decdiv�
               \count255=0 % compteur des it�rations�\idx*\count�
               \FOR\xxx = -2 to 1 \do \increment{% pour chaque��*\FOR�
                       \FOR\yyy = 0 to 1 \do \increment{% pixel du domaine��*\FOR�
                               \mandeltest\xxx\yyy% tester s'il est dans M��*\mandeltest�
                               \ifnum\mandelresult=1 % si oui,
                                       \plot(\xxx,\yyy)\plot(\xxx,-\yyy)% afficher les 2 points��*\plot�
                               \fi
                       }%
               }%
       \edef\plotstuff{$\scriptstyle\number\count255 $}% affiche la valeur du compteur�\idx*\scriptstyle\idx*\number\idx*\count�
       \plot(-1.99,0.92)% aux coordonn�es (-1.99 ; 0.92)��*\plot�
       }%
}
\xunit=3cm \yunit=3cm \mandel{400}{500}��\mandel�|{\includegraphics{mandelbrot.pdf}}

Afin d'obtenir un trac� pr�cis et assez fid�le � ce qu'est $\mathcal M$, nous avons demand� un grand nombre de pixels par unit� (400) et un nombre �lev� d'it�rations (500). Nous avons donc $3\times400$ pixels horizontalement et 400 pixels verticalement � tester c'est-�-dire \numprint{480000} tests � faire. Chacun ex�cute une boucle suppl�mentaire pouvant aller jusqu'� 500 it�rations. M�me si tous les tests ne proc�dent pas � ces 500 it�rations, il s'agit l� sans nul doute du plus grand nombre d'it�rations qu'il m'ait �t� donn� de programmer en \TeX{} : il y en a tr�s exactement \numprint{63430877} ! Compte tenu de la grandeur des arguments de �\mandel conduisant � cet incroyable nombre d'it�rations, la compilation de ce seul code demande de longues minutes. En outre, le nombre de pixels (c'est-�-dire de r�glures) � placer sur la page est extr�mement important ce qui requiert une augmentation de la m�moire de \TeX{}. Pour ce faire, les param�tres suivants ont �t� modifi�s :

\centrecode/main_memory = 10000000
extra_mem_bot = 20000000/

Ce dernier code, en raison du temps de compilation qu'il requiert, d�roge � la r�gle qui veut que chaque code g�n�re l'affichage qui se trouve dans la partie basse du cadre. Ce code a donc �t� compil� � part avec une version modifi�e de \texttt{tex} et le fichier pdf obtenu a �t� incorpor� sous le code.

\chapter{Aller plus loin dans la mise en forme}
\section{Formater un nombre}\idx*[|(]{formatter un nombre}
\Qu elle diff�rence y a t-il entre �\hbox{9876543,21012}� et �\numprint{9876543,21012}� ? Math�matiquement aucune, mais typographiquement, la diff�rence est �norme : elle se situe au niveau de ces petites espaces ins�cables qui s�parent les groupes de chiffres en les groupant trois par trois et qui font que, du premier coup d'\oe il, on sait que 9 est le chiffre des unit�s de millions. Il en va ainsi de la typographie fran�aise qui, par souci de lisibilit�, fixe comme r�gle d'ins�rer une espace fine ins�cable entre chaque groupe de trois chiffres.

Le but que nous nous fixons e de pouvoir formater n'importe quel nombre, on ne va s'imposer aucune limite sur le nombre de chiffres, pas plus dans la partie enti�re que dans la partie d�cimale. Par cons�quent, nous ne pourrons � aucun moment utiliser la primitive \idx\number puisque l'entier qui la suit doit �tre inf�rieur � $2^{31}-1$.

\subsection{Partie d�cimale}
La partie facile est de traiter la partie d�cimale puisqu'elle doit �tre parcourue de gauche � droite --~le sens de lecture de \TeX~-- afin d'ins�rer une espace fine (cr��e par la macro \verb|\numsep|) chaque fois que l'on a parcouru 3 chiffres. Pour cela, nous allons reprendre la macro �\reverse vue � la page~\pageref{reverse} en la modifiant l�g�rement. Cette macro offre la particularit� int�ressante de fournir du mat�riel purement d�veloppable ne produisant aucune sortie vers l'affichage jusqu'� ce que l'argument soit invers� en totalit�, moment il est dirig� vers l'affichage.

Sur ce mod�le, nous allons b�tir une macro r�cursive \verb|\formatdecpart@i| qui admet trois arguments d�limit�s. Le premier est l'entier qui repr�sente le nombre de chiffres parcourus et qu'il faudra tester par rapport � 3. Les deux autres sont les � r�servoirs � d�j� vus avec la macro �\reverse qui stockent les tokens et qui, en se passant de s�quence de contr�le d�finies par \verb|\def|, rendent la macro purement d�veloppable.

\showcode|\catcode`\@11
\protected\def\numsep{\kern0.2em }% \numsep est le s�parateur mis tous les 3 chiffres�\idx*\protected�

\def\formatdecpart#1{% #1=s�rie de chiffres��*\formatdecpart�
       \ifempty{#1}% si la partie d�cimale est vide��*\ifempty�
               {}% ne rien afficher
               {{,}\formatdecpart@i 1.#1..}% sinon, afficher la virgule et mettre en forme
}

% #1=compteur de caract�res #2= chiffre courant
% #3= chiffres restants     #4 = chiffres d�j� trait�s
\def\formatdecpart@i#1.#2#3.#4.{%
       \ifempty{#3}% si #2 est le dernier chiffre��*\ifempty�
               {#4#2}% le mettre en derni�re position et tout afficher, sinon
               {\ifnum#1=3 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
                       % si 3 chiffres sont atteint, rendre #1 �gal � 1 et
                       {\formatdecpart@i 1.#3.#4#2\numsep.}% mettre #2\numsep en dernier puis recommencer
                       % sinon, mettre #2 en derni�re position et recommencer
                       % tout en incr�mentant #1 de 1
                       {\expandafter\formatdecpart@i \number\numexpr#1+1.#3.#4#2.}%�\idx*\numexpr�
               }%
}
a) \formatdecpart{1234567}\qquad
b) \formatdecpart{987125}\qquad
c) \formatdecpart{56}\qquad
d) \edef\foo{\formatdecpart{2014}}\meaning\foo��*\formatdecpart�|

La virgule, qui joue le r�le de s�parateur d�cimal est ins�r�e entre accolades pour que cette virgule ne soit pas prise comme un s�parateur de liste si la macro est ex�cut�e en mode math�matique\idx*{mode!math�matique} car dans ce cas, elle serait suivie d'une espace.

\subsection{Partie enti�re}
La partie enti�re est plus difficile. La premi�re �tape sera de l�g�rement modifier la macro �\formatdecpart en la macro �\formatintpart pour que cette derni�re affiche le nombre qu'elle a trait�, mais � l'envers. Pour cela, il suffit de changer l'ordre des arguments \verb|#2| et \verb|#4| dans le texte de remplacement de \verb|\formatdecpart@i| :

\showcode|\catcode`\@11
\protected\def\numsep{\kern0.2em }% \numsep est le s�parateur mis tous les 3 chiffres�\idx*\protected�
\def\formatintpart#1{% #1=s�rie de chiffres��*\formatintpart�
       \formatintpart@i 1.#1..% appelle la macro r�cursive
}

% #1=compteur de caract�res #2= chiffre courant
% #3= chiffres restants     #4 = chiffres d�j� trait�s
\def\formatintpart@i#1.#2#3.#4.{%
       \ifempty{#3}% si #2 est le dernier chiffre��*\ifempty�
               {#2#4}% le mettre en premi�re position et tout afficher, sinon
               {\ifnum#1=3 \expandafter\firstoftwo\else\expandafter\secondoftwo
               \fi% si 3 chiffres sont atteint, rendre #1 �gal � 1 et
                       {\formatintpart@i 1.#3.\numsep#2#4.}% mettre "\numsep#2" en premier et recommencer
                       % sinon, mettre #2 en premi�re position et recommencer
                       % tout en incr�mentant #1 de 1
                       {\expandafter\formatintpart@i \number\numexpr#1+1.#3.#2#4.}%�\idx*\numexpr�
               }%
}
\catcode`\@12
a) \formatintpart{1234567}\qquad b) \formatintpart{987125}\qquad
c) \formatintpart{56}\qquad
d) \edef\foo{\formatintpart{2014}}\meaning\foo��*\formatintpart�|

Comme deux inversions s'annulent, le r�sultat serait celui que l'on attend si au lieu du nombre pass� comme argument � �\formatintpart, on passait le nombre invers�. On va donc utiliser la macro �\reverse et faire l'appel � la macro r�cursive de cette fa�on :

\centrecode-\expandafter\formatintpart@i\expandafter1\expandafter.\reverse{#1}..-

\noindent Le seul ennui est que �\reverse ne donne pas son r�sultat en un seul d�veloppement ! Mais, du fait de sa structure, l'affichage est fait � la toute fin, apr�s des instructions purement d�veloppables ne donnant aucun affichage. La primitive \idx\romannumeral va nous servir pour tout d�velopper en un coup jusqu'� l'affichage final. Pour stopper \idx\romannumeral \emph{avant} qu'elle ne voit les chiffres et ne s'en empare pour former un nombre romain, nous mettrons \idx\z@ dans l'argument de �\reverse telle sorte qu'il stoppe l'expansion et l'action de \idx\romannumeral. Comme  �\reverse inverse l'ordre, il faut �crire \idx\z@ en dernier pour qu'il soit en premier � la fin du traitement :

\showcode|\catcode`\@11
\def\formatintpart#1{% #1=s�rie de chiffres��*\formatintpart�
       \expandafter\formatintpart@i\expandafter1\expandafter.\romannumeral\reverse{#1\z@}..%�\idx*\romannumeral\idx*\z@�
}

\catcode`\@12
a) \formatintpart{1234567}\qquad b) \formatintpart{987125}\qquad
c) \formatintpart{56}\qquad
d) \edef\foo{\formatintpart{2014}}\meaning\foo��*\formatintpart�|

Mettre le tout en coh�rence pour former une macro �\formatnum est maintenant ais� :

\showcode|\catcode`\@11
\def\ifnodecpart#1{\if@nodecpart#1.\@nil}% teste si #1 est un entier��*\ifnodecpart�
\def\if@nodecpart#1.#2\@nil{\ifempty{#2}}��*\ifempty�

\def\formatnum#1{%��*\formatnum�
       \ifnodecpart{#1}% s'il n'y a pas de partie d�cimale��*\ifnodecpart�
               {\formatintpart{#1}}% formatter la partie enti�re
               {\formatnum@i#1\@nil}% sinon, formatter les deux parties
}

\def\formatnum@i#1.#2\@nil{%
       \formatintpart{#1}% formatte la partie enti�re��*\formatintpart�
       \formatdecpart{#2}% et la partie d�cimale��*\formatdecpart�
}

\catcode`\@12
a) \formatnum{3.1415926}\qquad
b) \formatnum{1987654.12301}\qquad
c) \edef\foo{\formatnum{0987654.12300}}$\foo$��*\formatnum�|

Un d�faut de notre macro saute aux yeux avec le dernier cas; elle ne supprime pas les z�ros inutiles. Et comme il est impossible d'utiliser \idx\number qui l'aurait fait, il va donc falloir �crire deux macros, purement d�veloppables, qui suppriment les z�ros inutiles d'un nombre entier lorsqu'ils sont au d�but pour l'une et � la fin pour l'autre.

\subsection{Supprimer les 0 inutiles de gauche}
Voici la macro �\removefirstzeros, purement d�veloppable, qui supprime les 0 au d�but de son argument :

\showcode|\catcode`\@11
\def\removefirstzeros#1{%��*\removefirstzeros�
       \removefirstzeros@i#1\quark% ajoute "\quark" en dernier��*\quark�
}
\def\removefirstzeros@i#1{% #1=chiffre courant
       \ifx\quark#1% fin atteinte donc nombre = 0
               \expandafter0% laisser un z�ro
       \else
               \ifx0#1% si le chiffre lu est un 0
                       \expandafter\expandafter\expandafter\removefirstzeros@i% recommencer
               \else% sinon remettre le chiffre #1 et tout afficher jusqu'� \removefirstzeros@i
                       \expandafter\expandafter\expandafter\removefirstzeros@ii
                       \expandafter\expandafter\expandafter#1%
               \fi
       \fi
}
\def\removefirstzeros@ii#1\quark{#1}��*\quark�
\catcode`\@12
a) \removefirstzeros{000325478}\qquad
b) \removefirstzeros{00000}\qquad
c) \edef\foo{\removefirstzeros{001000}}\meaning\foo\qquad
d) \long\def\>#1<{\detokenize{#1}}
  \expandafter\>\romannumeral\removefirstzeros{0123}<��*\removefirstzeros�|

La macro fonctionne bien sauf qu'au dernier cas, la forcer � donner le r�sultat en un d�veloppement avec \idx\romannumeral est un �chec puisque justement, les caract�res que laisse la macro sont des chiffres qui sont derechef convertis en un nombre romain. L'id�al serait de trouver une astuce pour rendre cette macro d�veloppable avec \idx\romannumeral sans rien changer � la macro. La r�ponse, non encore vue jusqu'� pr�sent tient dans le dernier point de la r�gle de la page~\pageref{definition.entier}.

Rappelons-nous que cette r�gle stipule que si \TeX{} s'attend � lire un nombre, les caract�res

\centrecode|-`\@|

\noindent sont lus comme la repr�sentation interne de l'entier \number-`\@{} car le code de caract�re de \verb|@| est 64\footnote{On aurait tout aussi bien pu �crire �\texttt{-`\string\a}� qui repr�sente \number-`\a\relax{} ou encore tout nombre n�gatif ou nul de la forme �\texttt{-`\char`\\\codeelement{car}}�.}. Mais le point int�ressant de cette r�gle est que \TeX{} \emph{continue} le d�veloppement maximal apr�s ces caract�res jusqu'� trouver un espace (qu'il absorbe) ou tout autre token (qu'il laisse tel quel). On comprend tout le b�n�fice que l'on peut tirer de cette r�gle ici. En effet, �\removefirstzeros ne dirige aucun token vers l'affichage tant qu'il n'a pas trouv� autre chose que 0. Par cons�quent, si

\centrecode/\romannumeral-`\@/

\noindent est plac� devant �\removefirstzeros, le d�veloppement maximal sera en route jusqu'� ce que quelque chose soit affich�, c'est-�-dire apr�s avoir mang� les 0 inutiles. De plus, \idx\romannumeral �valuant le nombre n�gatif \verb|-`\@|, aucun chiffre romain ne sera dirig� vers l'affichage.

\begin{regle}
Lorsqu'il est 1-d�velopp�, le code suivant

\centrecode|\romannumeral-`\<caract�re>|

\noindent effectue l'action � tout d�velopper au maximum jusqu'� trouver un token (absorb� si c'est un espace et laiss� tel quel sinon) qui stoppera le d�veloppement �.
\end{regle}

\showcode|\long\def\>#1<{\detokenize{#1}}
\expandafter\>\romannumeral-`\@\removefirstzeros{000123}<�\idx*\romannumeral�*\removefirstzeros�|

\subsection{Supprimer les 0 inutiles de droite}
Maintenant, il nous faut �crire la partie plus difficile, celle d'enlever les z�ros inutiles finaux. Pour cela, inutile de tout r�inventer, nous avons d�j� tout ce qu'il nous faut : il suffit d'inverser l'argument, d'enlever tous les z�ros de gauche puis d'inverser encore le r�sultat obtenu pour arriver � nos fins. Rien n'emp�che d'utiliser plusieurs \idx\romannumeral imbriqu�s qui se passent la main afin de provoquer le d�veloppement maximal dans le bon ordre.

On souhaiterait �crire

\centrecode-\reverse{\removefirstzeros{\reverse{<nombre>}}}-�*\reverse

\noindent mais �a serait oublier que \TeX{} n'�value pas ses arguments avant que la macro ne les lise. Il nous incombe donc de forcer le d�veloppement dans le bon ordre, c'est-�-dire d�velopper �\reverse\verb|{<nombre>}| en premier, puis �\removefirstzeros pour que le �\reverse chapeau agisse sur le nombre purg� de ses 0 de gauche. De plus, �\removefirstzeros doit �tre r�-�crit, car cette macro laissait un 0 si le nombre �tait nul, et ce comportement n'est pas souhaitable ici. La macro \verb|\removelastzeros@i| r�tablit le comportement souhait�.

Toute la \TeX nicit� r�side dans la macro chapeau �\removelastzeros o�, par le truchement de \idx\romannumeral, les arguments sont d�velopp�s dans le bon ordre.

\showcode|\catcode`\@11
\def\removelastzeros#1{%��*\removelastzeros�
       \exparg\reverse% inverser apr�s��*\reverse�
               {\romannumeral-`\.% tout d�velopper�\idx*\romannumeral�
                       \expandafter\removelastzeros@i% enlever les 0 de gauche apr�s
                       \romannumeral\reverse{#1\z@}\quark% avoir invers� #1��*\reverse\idx*\z@\idx*\romannumeral�
               }%
}
\def\removelastzeros@i#1{% enl�ve tous les 0 de gauche
       \unless\ifx\quark#1% si la fin n'est pas atteinte�\tidx*{unless}�*\quark�
               \ifx0#1% si le chiffre lu est un 0
                       \expandafter\expandafter\expandafter\removelastzeros@i% recommencer
               \else% sinon remettre le chiffre et tout afficher jusqu'� \removefirstzeros@i
                       \expandafter\expandafter\expandafter\removelastzeros@ii
                       \expandafter\expandafter\expandafter#1%
               \fi
       \fi
}
\def\removelastzeros@ii#1\quark{#1}��*\quark�
\catcode`\@12
a) \removelastzeros{0003254780}\qquad
b) \removelastzeros{00000}\qquad
c) \edef\foo{\removelastzeros{001000}}\foo\qquad
\long\def\>#1<{\detokenize{#1}}
d) \expandafter\>\romannumeral-`\.\removelastzeros{012300}<��*\removelastzeros\idx*\romannumeral�|

\subsection{G�rer le signe du nombre}
Nous voyons bient�t le bout du tunnel, il nous reste � parler du signe du nombre. Pour rester coh�rent avec \TeX{}, nous allons admettre qu'un nombre peut commencer par autant de signes \verb|+| et \verb|-|, mais que le signe math�matique du nombre affich� sera n�gatif si les signes �\verb|-|� sont en nombre impair. Pour cela, la macro �\formatnum va devoir transmettre son argument � une macro \verb|\formmatnum@i|, � arguments d�limit�s de type � r�servoirs communicants�. Ici, le d�limiteur sera �\verb|!|� puisque le �\verb|.|� est susceptible d'�tre contenu dans le nombre. La macro chapeau effectuera cet appel initial � la macro r�cursive :

\centrecode-\def\formatnum#1{\formatnum@i 1!#1!}-

Le premier argument d�limit�, qui tient lieu de r�servoir \no1, vaut 1 lors de l'appel initial. Ce r�servoir accumulera en premi�re position tous les signes rencontr�s au d�but du r�servoir \no2 qui situ� entre les deux points d'exclamation, dont la valeur initiale est le \verb|<nombre>| � formater. La macro \verb|\formatnum@i| va donc avoir un texte de param�tre d�fini ainsi

\centrecode-\def\formatnum@i#1!#2#3!{...}-

\noindent de fa�on � ce que \verb|#2| soit le premier caract�re du nombre � examiner et \verb|#3| soit les caract�res non encore trait�s. Il suffit de tester si ce caract�re \verb|#2| est \verb|+| ou \verb|-| et dans ce cas, le mettre en premi�re position dans le r�servoir \no1 et recommencer avec les arguments qui seront devenus �\verb|#2#1|� et \verb|#3|�. Si ce n'est pas le cas, cela veut dire que l'on a �puis� les signes situ�s au d�but du nombre. Il est alors temps de tester si le nombre dans le r�servoir \no1, constitu� de tous les signes rencontr�s suivis de 1, est lu par \TeX{} comme �gal � $-1$ et dans ce cas, afficher un �\verb|-|� puis passer la main � la mise en forme du nombre proprement dite.

On remarquera que si le nombre n'est constitu� que de signes \verb|+| ou \verb|-|, $+1$ ou $-1$ sera lu dans le premier r�servoir selon la parit� du nombre de signes \verb|-|. Enfin, dernier raffinement, une macro se chargera de remplacer dans l'argument de �\formatnum le s�parateur d�cimaux �virgule� en �point� avant de traiter le nombre. Ainsi, la virgule ou le point peuvent indiff�remment �tre utilis�s comme s�parateur d�cimal.

Voici le code complet :

\showcode|\catcode`\@11
\protected\def\numsep{\kern0.2em }% \numsep est le s�parateur mis tous les 3 chiffres�\idx*\protected�

\def\formatdecpart#1{% #1=s�rie de chiffres��*\formatdecpart�
       \ifempty{#1}% si la partie d�cimale est vide��*\ifempty�
               {}% ne rien afficher
               {{,}\formatdecpart@i 1.#1..}% sinon, afficher la virgule et mettre en forme
}

% #1=compteur de caract�res #2= chiffre courant
% #3= chiffres restants     #4 = chiffres d�j� trait�s
\def\formatdecpart@i#1.#2#3.#4.{%
       \ifempty{#3}% si #2 est le dernier chiffre��*\ifempty�
               {#4#2}% le mettre en derni�re position et tout afficher, sinon
               {\ifnum#1=3 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
                       % si 3 chiffres sont atteint, rendre #1 �gal � 1 et
                       {\formatdecpart@i 1.#3.#4#2\numsep.}% mettre #2\numsep en dernier puis recommencer
                       % sinon, mettre #2 en derni�re position et recommencer
                       % tout en incr�mentant #1 de 1
                       {\expandafter\formatdecpart@i \number\numexpr#1+1.#3.#4#2.}%�\idx*\numexpr�
               }%
}

\def\formatintpart#1{% #1=s�rie de chiffres��*\formatintpart�
       \expandafter\formatintpart@i\expandafter1\expandafter.%
       \romannumeral\reverse{#1\z@}..% appelle la macro r�cursive�\idx*\romannumeral\idx*\z@�
}

% #1=compteur de caract�res #2= chiffre � d�placer
% #3= chiffres restants     #4 = chiffres d�j� trait�s
\def\formatintpart@i#1.#2#3.#4.{%
       \ifempty{#3}% si #2 est le dernier chiffre � traiter��*\ifempty�
               {#2#4}% le mettre en premi�re position et tout afficher, sinon
               {\ifnum#1=3 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
                       % si 3 chiffres sont atteint, rendre #1 �gal � 1 et
                       {\formatintpart@i 1.#3.\numsep#2#4.}% mettre \numsep#2 en premier puis recommencer
                       % sinon, mettre #2 en derni�re position et recommencer
                       % tout en incr�mentant #1 de 1
                       {\expandafter\formatintpart@i\number\numexpr#1+1.#3.#2#4.}%
               }%
}
\def\removefirstzeros#1{%��*\removefirstzeros�
       \removefirstzeros@i#1\quark% ajoute "\quark" en dernier��*\quark�
}
\def\removefirstzeros@i#1{% #1=chiffre courant
       \ifx\quark#1% fin atteinte donc nombre = 0
               \expandafter0% laisser un z�ro
       \else
               \ifx0#1% si le chiffre lu est un 0
                       \expandafter\expandafter\expandafter\removefirstzeros@i% recommencer
               \else% sinon remettre le chiffre #1 et tout afficher jusqu'� \removefirstzeros@i
                       \expandafter\expandafter\expandafter\removefirstzeros@ii
                       \expandafter\expandafter\expandafter#1%
               \fi
       \fi
}
\def\removefirstzeros@ii#1\quark{#1}��*\quark�

\def\removelastzeros#1{%��*\removelastzeros�
       \exparg\reverse% inverser apr�s��*\reverse�
               {\romannumeral-`\.% tout d�velopper�\idx*\romannumeral�
                       \expandafter\removelastzeros@i% enlever les 0 de gauche apr�s
                       \romannumeral\reverse{#1\z@}\quark% avoir invers� #1��*\reverse\idx*\z@\idx*\romannumeral�
               }%
}
\def\removelastzeros@i#1{% enl�ve tous les 0 de gauche
       \unless\ifx\quark#1% si la fin n'est pas atteinte�\tidx*{unless}�*\quark�
               \ifx0#1% si le chiffre lu est un 0
                       \expandafter\expandafter\expandafter\removelastzeros@i% recommencer
               \else% sinon remettre le chiffre et tout afficher jusqu'� \removefirstzeros@i
                       \expandafter\expandafter\expandafter\removelastzeros@ii
                       \expandafter\expandafter\expandafter#1%
               \fi
       \fi
}
\def\removelastzeros@ii#1\quark{#1}��*\quark�

% renvoie vrai s'il n'y a pas de partie d�cimale
\def\if@nodecpart#1.#2\@nil{\ifempty{#2}}��*\ifempty�

\def\formatnum#1{\formatnum@i1!#1!}��*\formatnum�

% #1 = <s�rie de signes> suivie de "1"
% #2 = caract�re courant
% #3 = caract�res non trait�s
\def\formatnum@i#1!#2#3!{%
       \ifx+#2\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               {\ifempty{#3}% si #2=+ et #3 est vide��*\ifempty�
                       {\number#1 }% afficher "+1" ou "-1" (il n'y avait que des signes)�\idx*\number�
                       {\formatnum@i#2#1!#3!}% sinon, mettre le signe #2 devant #1
               }
               {\ifx-#2\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
                       {\ifempty{#3}% si #2=- et #3 est vide��*\ifempty�
                               {\number#1 }% afficher "+1" ou "-1" (il n'y avait que des signes)�\idx*\number�
                               {\formatnum@i#2#1!#3!}% sinon, mettre le signe #2 devant #1
                       }% #2 est le dernier caract�re qui n'est pas un signe + ou -
                       {\ifnum#1<0 -\fi% si "<signes>1" est <0 afficher un "-"�\defline\aaa�
                       \formatnum@ii{#2#3}% formatter le nombre form� avec "#2#3""
                       }%
               }%
}

\def\formatnum@ii#1{%
       \if@comma{#1}% si #1 comporte une virgule
               {\formatnum@iii#1\@nil}% la remplacer par un "." et recommencer
               {\if@nodecpart#1.\@nil% puis si les chiffres restants sont un entier
                       {\formatintpart{#1}}% formatter l'entier
                       {\formatnum@iv#1\@nil}% sinon, formatter le nombre
               }%
}

\def\formatnum@iii#1,#2\@nil{\formatnum@ii{#1.#2}}

\def\formatnum@iv#1.#2\@nil{% formatte le nombre d�cimal #1.#2
       \exparg\formatintpart{\romannumeral-`\.\removefirstzeros{#1}}%�\idx*\romannumeral�*\removefirstzeros�*\exparg�
       \exparg\formatdecpart{\romannumeral-`\.\removelastzeros{#2}}%��*\formatdecpart�*\removelastzeros�*\exparg�
}

\def\if@comma#1{\if@comma@i#1,\@nil}% teste la pr�sence d'un virgule dans #1
\def\if@comma@i#1,#2\@nil{\ifempty{#2}\secondoftwo\firstoftwo}��*\ifempty�
\catcode`\@12

a) \formatnum{3,141592653589793238462643383279502884197169399375105820974944592}\par
b) \formatnum{---+69874}\qquad
c) \formatnum{0032100,98000}\qquad
d) \formatnum{+++010.01100}\qquad
e) \formatnum{-+--+}\qquad
f) \formatnum{---00.0000}\qquad
g) \formatnum{+99,0000}\qquad
h) \formatnum{.123456}\par
i) \edef\foo{\formatnum{-+-+-010500,090900}}\meaning\foo��*\formatnum�|\idx*[|)]{formatter un nombre}

\section{Permettre � une boite encadr�e de franchir des pages}
\subsection{Couper une boite verticale}\idx*[|(]{couper une boite verticale}
Cela avait �t� clairement annonc� � la page~\pageref{boite.insecable} : toute boite construite avec les primitives \idx\hbox, \idx\vbox ou \idx\vtop est \emph{ins�cable}. C'est effectivement le cas � un petit mensonge pr�s\ldots{} Si une boite \emph{verticale} est stock�e dans un registre de boite, il est possible de couper la boite ainsi stock�e en deux boites verticales. La primitive qui permet cette op�ration est \idx\vsplit\footnote{En revanche, les boites horizontales \texttt{\string\hbox} sont \emph{vraiment} ins�cables, il n'existe h�las pas de primitive \texttt{\string\hsplit}.}.

\begin{regle}
Si \verb|<x>| est un registre de boite auquel on a assign� une boite verticale (construite avec \idx\vbox ou \idx\vtop) et si \verb|<y>| est un num�ro de registre de boite, alors

\centrecode-\setbox <y>=\vsplit <x> to <dimension>-\idx*\vsplit

\noindent va commander � \TeX{} de parcourir la boite contenue dans le registre \no\verb|<x>| et op�rer la meilleure coupure possible pour g�n�rer une boite de hauteur \verb|<dimension>|. Le registre \no\verb|<y>| contiendra cette nouvelle boite tandis que le registre \verb|<x>| contiendra la boite initiale amput�e d'autant. Si la \verb|<dimension>| est suffisamment grande pour que la coupure englobe la totalit� de la boite initiale \verb|<x>|, le registre \verb|<x>| devient vide, c'est-�-dire positif au test \tidx{ifvoid}.

Le m�canisme de coupure de boite verticale est similaire � celui des coupures de pages. En particulier, les objets � volatils � sont supprim�s � la coupure (\idx{p�nalit�}s et espaces verticaux de type \idx[|etc]\kern\forbidindex\kern{} ou \idx\vskip).

Enfin, un ressort appel� \idx\splittopskip est ins�r� au sommet de la boite restante \verb|<x>|.
\end{regle}

Le code ci-dessous illustre cette r�gle, o� la boite initiale contient 4 lignes, chacune enferm�e dans une \idx\hbox :

\showcode/\setbox0=\vbox{%�\idx*[|etc]\setbox\forbidindex\setbox�
       \hbox{Premi�re ligne}�\idx*\hbox�
       \hbox{Deuxi�me ligne}
       \hbox{Avant-derni�re ligne}
       \hbox{Derni�re ligne}
}

\frboxsep=0pt % aucun espace entre le contenu et l'encadrement��*\frboxsep�
Boite initiale de hauteur \the\ht0 {} : \frbox{\copy0 }��*\frbox�
\splittopskip0pt % ne rajouter aucun espace au sommet de la boite restante�\idx*\splittopskip�
\setbox1=\vsplit0 to 22pt % couper la boite � 22pt de hauteur�\idx*\setbox\idx*\vsplit�

Boite 1 de hauteur \the\ht1 {} : \frbox{\box1 }

Boite 0 de hauteur \the\ht0 {} : \frbox{\box0 }�\idx*\box\idx*\the\idx*\ht �*\frbox�/

Il faut noter qu'un message d'avertissement\idx*{message d'avertissement} est �mis lorsque la coupure est faite : �\texttt{Underfull \string\vbox{} (badness 10000) detected}�. Ce message indique que la boite \no1 est insuffisamment remplie\idx*{boite insuffisamment remplie}, ce que l'on peut constater visuellement. L'explication tient au fait que seules deux lignes ont pu �tre log�es verticalement dans 22 points. Mais ces deux lignes ne remplissent pas la totalit� de ces 22 points qui sont impos�s. Pour �viter de garder une boite insuffisamment pleine, on peut utiliser

\centrecode-\setbox1=\vbox{\unvbox1 }-\idx*\unvbox

\noindent afin que la boite \no1 soit � extraite � de la \idx\vbox de hauteur impos�e et, ayant repris sa dimension naturelle, soit � nouveau enferm�e dans une \idx\vbox.

Pour emp�cher \TeX{} d'�mettre un message d'avertissement\idx*{message d'avertissement} lors de la coupe de la boite \no0, il faut agir sur l'entier \idx\vbadness qui repr�sente le seuil de m�diocrit� au-del� duquel un message d'avertissement\idx*{message d'avertissement} n'est plus �mis concernant une boite verticale (\idx\hbadness est le pendant pour les boites horizontales). Nous allons donc sauvegarder cet entier puis lui assigner l'entier \numprint{10000} qui repr�sente la m�diocrit� maximale, et apr�s avoir coup� la boite avec \idx\vsplit, restaurer \idx\vbadness � la valeur initiale.

\showcode/\setbox0=\vbox{%�\idx*\setbox�
       \hbox{Premi�re ligne}
       \hbox{Deuxi�me ligne}
       \hbox{Avant-derni�re ligne}
       \hbox{Derni�re ligne}
}

\edef\restorevbadness{\vbadness=\the\vbadness\relax}% restaurera le \vbadness�\idx*\the\idx*\vbadness�
\vbadness=10000 % plus d'avertissement pour boite verticale�\idx*{message d'avertissement}\idx*\vbadness�
\frboxsep=0pt % aucun espace entre le contenu et l'encadrement��*\frboxsep�
Boite initiale de hauteur \the\ht0 {} : \frbox{\copy0 }�\idx*\the\idx*\copy �*\frbox�
\splittopskip0pt % ne rajouter aucun espace au sommet de la boite restante�\idx*\splittopskip�
\setbox1=\vsplit0 to 22pt % couper la boite � 22pt de hauteur�\idx*\setbox\idx*\vsplit�
\setbox1=\vbox{\unvbox1 }% la boite 1 prend la hauteur naturelle�\idx*\unvbox\idx*\vbox�
\restorevbadness\relax% restaure le \vbadness

Boite 1 de hauteur \the\ht1 {} : \frbox{\box1 }

Boite 0 de hauteur \the\ht0 {} : \frbox{\box0 }�\idx*\box\idx*\the\idx*\ht �*\frbox�/

On constate bien que la boite \no1 a repris la hauteur naturelle et devient donc la boite contenant le plus de lignes possible dans \verb|22pt| de hauteur.

Il est en revanche assez inexplicable que la somme des deux hauteurs ne soit pas �gale � la hauteur de la boite initiale. Il manque

\[34.024\text{\ttfamily pt}-2\times15.024\text{\ttfamily pt}\approx 4\text{\ttfamily pt}\]

Cette hauteur manquante est celle qui s�pare la fronti�re inf�rieure de la boite \no1 de la fronti�re sup�rieure de la boite \no0. Ce \idx{ressort d'interligne} a disparu � la coupure, comme le font tous les ressorts aux coupures de page ou de ligne.\idx*[|)]{couper une boite verticale}

\subsection{Couper � la bonne hauteur}
Avant de b�tir un algorithme permettant de composer un texte dans un cadre qui franchit des pages, il reste tout de m�me une question essentielle : comment connaitre la hauteur qui reste � composer dans la page en cours ? Deux nouvelles primitives de \TeX{} vont nous permettre de r�pondre � cette question :

\begin{itemize}
       \item \idx\pagetotal est la dimension accumul�e verticalement jusqu'� la fin du pr�c�dent paragraphe enti�rement compos�;
       \item \idx\pagegoal est la dimension verticale du texte � composer dans la page en cours.
\end{itemize}

La dimension \idx\pagetotal n'est pas actualis�e en permanence, mais seulement apr�s chaque paragraphe compos�. Par ailleurs, au tout d�but de la construction d'une page, lorsqu'elle est vide, \idx\pagetotal vaut \numprint[pt]0 alors que \idx\pagegoal vaut \numprint[pt]{16383,99999}\footnote{Lire le \TeX book page~133 et plus g�n�ralement le chapitre 15 en entier.}, soit \idx\maxdimen. Par cons�quent, notre futur algorithme devra tenir compte de cette sp�cificit� au d�but des pages. Afin que \idx\pagegoal prenne une valeur refl�tant la hauteur de la page, il faudra donc, avant de mesurer quoi que ce soit, faire en sorte que la nouvelle page ne soit pas vide . Ins�rer le mat�riel vertical �\idx\hbox\verb-{}-\idx\nointerlineskip� tiendra lieu de remplissage de haut de page, tout en ne prenant aucune place verticalement. Ainsi, apr�s cette op�ration, \idx\pagegoal sera �gal � la hauteur de la zone de texte en haut d'une page. Nous sommes maintenant assur�s que, quelles que soient les circonstances, la diff�rence entre \idx\pagegoal et \idx\pagetotal sera la hauteur de l'espace vertical disponible restant dans la page en cours.

Ces deux primitives �taient ce qui nous manquait pour construire l'algorithme permettent de couper $n$ fois une boite verticale pour la loger sur $n+1$ pages.

Nous allons d'abord d�cider que le contenu � afficher dans un cadre sera compris entre les macros �\breakpar et\verb|\endbreakpar|. La premi�re macro sera charg�e d'assigner � un registre de boite verticale tout ce qui se trouvera jusqu'� \verb|\endbreakpar|. Pour cela, cette macro utilisera \idx\bgroup au lieu de �\verb|{|� pour d�limiter le d�but de la boite alors que \verb|\endbreakpar| utilisera \idx\egroup pour marquer la fin de la boite verticale. La macro �\breakpar aura �galement pris soin, en d�but de boite, de diminuer la dimension horizontale \idx\hsize de cette boite. En effet, la largeur du texte � encadrer doit tenir compte de l'�paisseur de la r�glure d'encadrement �\frboxrule et de l'espace entre le texte et cette r�glure �\frboxsep, chacune de ces dimensions devant �tre compt�e deux fois, une fois pour la r�glure de gauche et une fois pour celle de droite.

En ce qui concerne le cadre proprement dit, il faut bien garder � l'esprit que selon les cas, les encadrements pourront �tre de 4 types diff�rents :
\begin{enumerate}
       \item cadre plein (\kern1pt {\frboxsep=0pt \framebox{\phantom M}}\kern1pt ) dans le cas o� l'espace restant dans la page en cours permet de loger le cadre dans sa totalit�;
\end{enumerate}

\noindent Si le cadre ne peut loger sur la page en cours, 3 autres types sont possibles :
\begin{enumerate}[start=2]
       \item cadre de d�but (\kern1pt {\frboxsep=0pt \framebox[ULR]{\phantom M}}\kern1pt );
       \item cadre interm�diaire (\kern1pt {\frboxsep=0pt \framebox[LR]{\phantom M}}\kern1pt ) dans le cas o� le texte � encadrer est tellement long qu'il faut une ou plusieurs pages interm�diaires entre le d�but du cadre et la fin;
       \item cadre de fin (\kern1pt {\frboxsep=0pt \framebox[DLR]{\phantom M}}\kern1pt ).
\end{enumerate}

% rappeler o� a �t� cr��e la macro \framebox
Pour tracer ces cadres, la macro �\framebox vue � la page~\pageref{framebox} va nous �tre d'un grand secours, il suffira de sp�cifier le bon argument optionnel pour avoir le cadre du type souhait�.

Dans les grandes lignes, l'algorithme va fonctionner de cette mani�re :

\begin{algo}
       \item capturer et composer dans une \idx\vbox de largeur appropri�e tout ce qui se trouve entre �\breakpar et \verb|\endbreakpar|, stocker cette boite dans le registre \verb|\remainbox| et aller au point \no2;
       \item macro �\splitbox
       \begin{algo}
               \item si \verb|\remainbox| est vide : fin du processus
               \item sinon, aller au point \no3.
       \end{algo}
       \item macro \verb|\splitbox@i|
       \begin{algo}
               \item si \verb|\remainbox|, une fois encadr�, loge sur l'espace restant dans la page, l'encadrer avec le cadre \no1 ou \no4, et fin du processus;
               \item sinon couper \verb|\remainbox| � une hauteur correspondant � celle de l'espace restant sur la page; encadrer le registre de boite obtenu (\verb|\partialbox|) avec le cadre \no2 ou \no3, composer la page en cours et aller au point \no2 avec la boite restante \verb|\remainbox|.
       \end{algo}
\end{algo}

Pour mener � bien cet algorithme, nous avons � �crire 5 macros diff�rentes : �\breakpar, \verb|\endbreakpar|, �\splitbox, \verb|\splitbox@i| ainsi qu'une macro qui affiche la boite � encadrer \verb|\printpartialbox|. Nous devrons correctement g�rer l'argument optionnel de �\framebox (o� les lettres �UDRL� sp�cifient les r�glures � afficher) pour choisir selon les cas, le bon encadrement. Pour ce faire, nous stockerons dans la macro \verb|\rule@arg| les lettres devant �tre pass�es � cet argument optionnel.
\grandsaut

Avant d'entrer dans le vif du sujet, il est n�cessaire d'examiner ce qui se passe en haut d'une page : afin que dans la mesure du possible, les lignes de base des premi�res lignes de chaque page se situent toutes � la m�me position verticale, le ressort \idx\topskip est ins�r� en haut de chaque page. Sa valeur est diminu�e de la hauteur de la premi�re ligne et si le r�sultat est n�gatif, le ressort \verb|0pt| est ins�r�. Plain-\TeX{} prend \idx\topskip �gal � \verb|10pt| ce qui assure que toutes les premi�res lignes dont la hauteur est inf�rieure ou �gale � \verb|10pt| commenceront � la m�me position verticale dans les pages.

Pour notre probl�me, si une boite doit �tre coup�e, il ne faut pas qu'un ressort en haut de page soit ins�r� avant le cadre restant (\kern1pt {\frboxsep=0pt \framebox[LR]{\phantom M}} ou {\frboxsep=0pt \framebox[DLR]{\phantom M}}\kern1pt ) : le haut des r�glures du cadre doit exactement co�ncider avec le bord sup�rieur de la zone de texte. Par cons�quent, \idx\topskip sera pris �gal � \verb|0pt|. Avant de proc�der � cette assignation, la valeur de \idx\topskip sera copi�e dans \idx\splittopskip qui joue le m�me r�le que \idx\topskip dans les boites r�siduelles apr�s une coupure par \idx\vsplit. Ce faisant, � chaque d�but de page, on s'assure que la premi�re ligne dans le cadre se situe � la m�me position verticale que les premi�res lignes des pages � normales �.
\grandsaut

Venons-en au c\oe ur du probl�me : � quelle hauteur allons-nous demander la coupure de la boite \verb|\remainbox| ? Au premier abord, on pourrait �tre tent� de r�pondre \idx*\pagegoal\idx*\pagetotal{}\verb|\pagegoal-\pagetotal| mais ce serait ignorer l'encombrement vertical de \verb|\frboxsep+\frboxrule|, requis par les �ventuelles r�glures (sup�rieures ou inf�rieures) d'�paisseur �\frboxrule et les espaces �\frboxsep qui les suivent ou les pr�c�dent. Il va de soi que selon les cas, ces r�glures sont pr�sentes soit toutes les deux (cas du cadre {\frboxsep=0pt \framebox{\phantom M}}\kern1pt ), soit seulement une des deux (cadre {\frboxsep=0pt \framebox[ULR]{\phantom M}} ou {\frboxsep=0pt \framebox[DLR]{\phantom M}}\kern1pt ), soit aucune (cadre \kern1pt {\frboxsep=0pt \framebox[LR]{\phantom M}}\kern 1pt ). Nous devons �tre rigoureux pour ne pas demander trop ou trop peu de hauteur de coupure.

Pour nous faciliter la t�che, nous allons stocker dans la macro \verb|\coeff@rule| le nombre de r�glures horizontales qui restent � afficher. Dans la macro chapeau, il sera initialis� � 2 puisque les deux r�glures sont encore � afficher. Ce coefficient sera ensuite pris �gal � 1 d�s que la premi�re coupure sera faite puisque la r�glure sup�rieure ne sera plus � afficher.

Du c�t� du calcul, il faut d�cider si une coupure de \verb|\remainbox| doit avoir lieu ou pas. La r�ponse est positive si sa dimension verticale totale (hauteur + profondeur) est sup�rieure � l'espace disponible sur la page en cours auquel on a soustrait l'espace requis pour les r�glures horizontales restantes. Math�matiquement, une coupure doit �tre faite si $\verb|\ht\remainbox|+\verb|\dp\remainbox|$ est strictement sup�rieur � $\verb|\pagegoal|-\verb|\pagetotal|-(\verb|\frboxsep|+\verb|\frboxrule|)\times\verb|\coeff@rule|$. Nous appellerons $D_v$ cette derni�re quantit� et la stockerons dans un registre de dimension appel� \verb|\cut@ht|.

Si la coupure doit �tre faite, � quelle hauteur doit �tre coup�e \verb|\remainbox| ? Comme une coupure est faite, la r�glure horizontale de fin de cadre ne se trouvera pas sur la page recevant la boite coup�e. Par cons�quent, la hauteur de coupure est $D_v$ augment�e de $\verb|\frboxsep|+\verb|\frboxrule|$.

Voici comment va op�rer la macro \verb|\splitbox@i| :

\begin{itemize}
       \item le registre de dimension \verb|\cut@ht| re�oit la hauteur $D_v$;
       \item si une coupure doit �tre faite, la dimension $\verb|\frboxsep|+\verb|\frboxrule|$ est ajout�e � \verb|\cut@ht|;
       \item \verb|\remainbox| est coup�e � la hauteur \verb|\cut@ht| et la boite obtenue est stock�e dans le registre \verb|\partialbox|;
       \item on rend \verb|\coeff@rule| �gal � 1 puisque la r�glure sup�rieure ne peut plus �tre pr�sente;
       \item si \verb|\splitbox@i| d�tecte que la coupure n'est pas n�cessaire, \verb|\remainbox| sera copi�e dans \verb|\partialbox| et \verb|\cut@ht| re�oit la hauteur verticale totale de \verb|\partialbox|;
\end{itemize}

Nous sommes bient�t au bout du tunnel, mais il y a un dernier raffinement auquel nous devons penser. Comment s'assurer que les r�glures verticales des encadrements �{\frboxsep=0pt \framebox[ULR]{\phantom M}}� et �{\frboxsep=0pt \framebox[LR]{\phantom M}}� iront jusqu'en bas de la page ? En effet, si nous encadrons avec

\centrecode-\expandafter\framebox\expandafter[\rule@arg]{\vbox{\unvbox\partialbox}}-\idx*\unvbox�*\framebox

\noindent le �\verb|\vbox{\unvbox\partialbox}|� va redonner � \verb|\partialbox| sa hauteur naturelle (plus petite que \verb|\cut@ht|) et l'encadrement n'atteindra pas exactement le bas de la page. Pour nous pr�munir de cette petite perte de hauteur, nous devons imposer un cadre de hauteur \verb|\cut@ht|, car ce registre contient la hauteur totale verticale du texte � encadrer. On �crira donc dans l'argument de �\framebox

\centrecode-\vbox to\cut@ht{\unvbox\partialbox\vss}-\idx*\unvbox\idx*\vss

Le ressort \idx\vss se charge de rattraper la diff�rence entre \verb|\cut@ht| et la hauteur naturelle de \verb|\partialbox|.
\grandsaut

Le code ci-dessous est un de ceux qui d�rogent � ce qui est la r�gle dans ce livre. Le r�sultat du code n'est pas pr�sent� celui qui d�coule de la compilation de ce code, car pour des raisons de place, les pages obtenues ont �t� r�duites et pr�sent�es les unes � c�t� des autres.

\errcode/\catcode`@11
\newbox\remainbox�\idx*\newbox�
\newbox\partialbox�\idx*\newbox�
\newdimen\cut@ht�\idx*\newdimen�

\def\breakpar{%��*\breakpar�
       \par\nointerlineskip% termine le paragraphe pr�c�dent�\idx*\nointerlineskip�
       \vskip\frboxsep\relax% et saute une petite espace verticale�\idx*\vskip�*\frboxsep�
       \begingroup
               \splittopskip\topskip% \topskip en haut des boites coup�es�\idx*\splittopskip\idx*\topskip�
               \topskip=0pt % neutraliser le \topskip�\idx*\topskip�
               % nbre de r�glures horizontales contribuant � l'encadrement restant (2 au d�but)
               \def\coeff@rule{2}%
               \setbox\remainbox=\vbox\bgroup% compose la boite apr�s avoir...�\idx*\setbox\idx*\vbox\idx*\bgroup�
                       \advance\hsize by -2\dimexpr\frboxrule+\frboxsep\relax% ajust� sa largeur�\idx*\advance�*\frboxrule�
}

\def\endbreakpar{%
               \egroup% fin de la composition de la boite�\idx*\egroup�
               \def\rule@arg{ULR}% prendre l\cut@htes r�glures d'encadrement haute, gauche et droite
               \splitbox% puis, aller � l'algorithme de coupure��*\splitbox�
       \endgroup% une fois fini, sortir du groupe semi-simple
}

\def\splitbox{%��*\splitbox�
       \ifvoid\remainbox% si la boite est vide, c'est la fin du processus�\tidx*{ifvoid}�
               \par\nointerlineskip% termine le paragraphe pr�c�dent�\idx*\nointerlineskip�
               \vskip\frboxsep\relax% et saute un petit espace vertical�\idx*\vskip�*\frboxsep�
       \else% sinon
               \expandafter\splitbox@i% aller � \splitbox@i
       \fi
}

\def\splitbox@i{%
       \hbox{}% composer un noeud en mode vertical�\idx*\hbox\idx*{mode!vertical}�
       \nointerlineskip% pas de ressort d'interligne�\idx*\nointerlineskip�
       % calculer la dimension verticale disponible dans la page pour le texte de la boite
       \cut@ht=\dimexpr\pagegoal-\pagetotal-(\frboxsep+\frboxrule)*\coeff@rule\relax�\idx*\dimexpr\idx*\pagegoal\idx*\pagetotal�*\frboxsep�*\frboxrule�
       % si dimension totale du texte > dimension disponible pour le texte
       \ifdim\dimexpr\ht\remainbox+\dp\remainbox>\cut@ht% si une coupure doit �tre faite�\tidx*{ifdim}�
                       \advance\cut@ht\dimexpr%   augmenter Dv de l'espace verticale lib�r�e
                               +\frboxsep+\frboxrule% par la r�glure inf�rieure qui n'est pas sur cette page
                               \relax
               \edef\old@vbadness{\the\vbadness}% sauvegarder \badness�\idx*\the\idx*\vbadness�
               \vbadness=10000 % d�sactive les avertissement lors de la coupure�\idx*\vbadness\idx*{message d'avertissement}�
               \def\coeff@rule{1}% ne prendre en compte que r�glure D + espace D
               \setbox\partialbox=\vsplit\remainbox to\cut@ht% coupe � la hauteur calcul�e�\idx*\setbox\idx*\vsplit�
               % \partialbox retrouve sa hauteur naturelle
               \setbox\partialbox=\vbox{\unvbox\partialbox}%�\idx*\setbox\idx*\vbox\idx*\unvbox�
               \vbadness=\old@vbadness\relax% restaure \vbadness�\idx*\vbadness�
               \printpartialbox% imprime la boite partielle
               \vfill\eject% et compose la page en cours�\idx*\vfill\idx*\eject�
       \else% si une coupure n'est pas n�cessaire :
               \setbox\remainbox\vbox{\unvbox\remainbox}% reprendre la hauteur naturelle�\idx*\setbox\idx*\vbox\idx*\unvbox�
               \setbox\partialbox=\box\remainbox% \partialbox devient \remainbox
                                                % et cette derni�re devient vide�\idx*\box�
               \cut@ht=\dimexpr\ht\partialbox+\dp\partialbox\relax% hauteur � encadrer�\idx*\the\idx*\ht�
               \edef\rule@arg{\rule@arg D}% ajouter "D" aux r�glures � tracer
               \printpartialbox% afficher la boite restante
       \fi
       \splitbox��*\splitbox�
}

\def\printpartialbox{% imprime \partialbox
       \expandafter\framebox\expandafter[\rule@arg]{%
               \vbox to\cut@ht{\unvbox\partialbox\vss}}%��*\framebox\idx*\vbox\idx*\unvbox\idx*\vss�
       \def\rule@arg{LR}% ne mettre que les r�glures d et g
}

\def\dummytext#1{%
       \for\xx=1to#1\do% composer #1 fois la phrase suivante :��*\for�
               {Ceci est un texte sans aucun int\'er\^et dont le seul but est de meubler
               la page artificiellement.
               }%
}

\catcode`@12
\dummytext{5}
\frboxsep=5pt ��*\frboxsep�

\breakpar
       \dummytext{70}
\endbreakpar��*\breakpar�

\dummytext{5}/{\frboxrule=1pt \frboxsep=0pt \leavevmode
\hfill\frbox{\includegraphics[scale=0.15]{pg0001.pdf}}\hfill
\frbox{\includegraphics[scale=0.15]{pg0002.pdf}}\hfill
\frbox{\includegraphics[scale=0.15]{pg0003.pdf}}\hfill\null
}

\subsection{Couper un paragraphe en lignes}
Maintenant que le m�canisme de coupure � l'aide de \idx\vsplit est un peu maitris�, nous allons le mettre � profit pour couper une boite verticale en lignes, chacune d'entre elles �tant contenue dans une boite. L'�norme int�r�t est qu'il devient alors possible d'effectuer une action pour chaque \emph{ligne} d'un ou plusieurs paragraphes. On pourra par exemple les num�roter ou afficher quelque chose dans la marge de gauche ou de droite. Il deviendra m�me possible d'agir sur la boite elle-m�me, pour l'encadrer par exemple.

� quelle hauteur faudra-t-il couper la boite contenant le tout pour n'obtenir qu'une seule ligne ? La question m�rite d'�tre pos�e car nous n'avons aucune indication sur la hauteur d'une ligne. La m�thode consiste � demander une coupure � une hauteur nulle. Cela va �videmment provoquer une �\texttt{overful vbox}� puisque rien ne peut tenir dans 0pt de hauteur. Il va donc falloir, le temps de la coupure, d�sactiver le m�canisme qui guette si une boite est trop remplie. \TeX{} dispose de la primitive \idx\vfuzz qui contient une dimension, seuil au-del� duquel est �mis un avertissement\idx*{message d'avertissement} lorsqu'une boite verticale d�borde (\idx\hfuzz est l'�quivalent pour les boites horizontales)\idx*{d�bordement de boite}. Il suffira donc de dire que \verb|\vfuzz=\maxdimen| pour s'assurer qu'aucun avertissement\idx*{message d'avertissement} n'est �mis lors du d�bordement d'une boite verticale, quelle que soit la valeur de ce d�bordement.

\showcode/\setbox0=\vbox{%�\idx*\setbox�
       \hsize=5cm �\idx*\hsize�
       Ceci est un texte sans aucun int�r�t dont le seul but est de meubler
       la page de fa�on artificielle.
}

Boite 0 : \copy0 % affiche la boite totale�\idx*\copy�
\medbreak�\idx*\medbreak�

\edef\restorevfuzz{\vfuzz=\the\vfuzz\relax}% appel�e apr�s la coupure�\idx*\the\idx*\vfuzz�
\vfuzz=\maxdimen% annule les avertissements pour d�bordement�\idx*\maxdimen\idx*{message d'avertissement}\idx*\vfuzz�
\splittopskip=0pt % ne rajouter aucun espace au sommet de la boite restante�\idx*\splittopskip�
\setbox1=\vsplit0 to 0pt % couper la boite � 0pt de hauteur�\idx*\setbox\idx*\vsplit�
\restorevfuzz% restaurer \vfuzz
\setbox1=\vbox{\unvbox1}% redonner � la boite sa hauteur d'origine�\idx*\unvbox\idx*\vbox�

Boites 1+0 : \vbox{%
       \offinterlineskip% annule le ressort d'interligne�\idx*\offinterlineskip�
       \box1 % affiche la premi�re ligne�\idx*\box�
       \box0 %affiche les lignes restantes
}/

Comme on l'a d�j� constat�, les ressorts disparaissent lors des coupures et donc ici, nous avons perdu le ressort d'interligne entre la 1\iere{} et la 2\ieme{} ligne. Si l'on veut afficher les lignes une par une, telles qu'elles auraient �t� affich�es lors d'une composition normale, on doit absolument r�cup�rer les ressorts mang�s lors des coupures pour les ins�rer entre chaque ligne. Si l'on appelle \verb|\htbefore| la hauteur de la boite \no0 avant la coupure, alors, la longueur verticale du mat�riel mang� � la coupure est

\centrecode|\htbefore-(\ht0+\dp0+\ht1+\dp1)|

On peut le v�rifier :

\label{recup.espace.vertical}\showcode/\def\vdim#1{\dimexpr\ht#1+\dp#1\relax}% hauteur totale de la boite #1��*\vdim\idx*\dimexpr\idx*\ht\idx*\dp�
\setbox0=\vbox{%�\idx*\vbox\idx*\setbox�
       \hsize=5cm Ceci est un texte sans aucun int�r�t dont le seul but est�\idx*\hsize�
       de meubler la page de fa�on artificielle.
}
\edef\htbefore{\the\vdim0}% hauteur de la boite 0�\idx*\the �*\vdim�

Boite 0 : \copy0 % affiche la boite totale�\idx*\copy�
\medbreak�\idx*\medbreak�

\edef\restoreparam{%
       \vfuzz=\the\vfuzz\relax% sauvegarde le \vfuzz�\idx*\the\idx*\vfuzz�
       \splittopskip=\the\splittopskip% et \splittopskip�\idx*\splittopskip�
}%
\vfuzz=\maxdimen% annule les avertissements pour d�bordement�\idx*\vfuzz\idx*\maxdimen\idx*{message d'avertissement}�
\splittopskip=0pt % ne rajouter aucun espace au sommet de la boite restante�\idx*\splittopskip�
\setbox1=\vsplit0 to 0pt % couper la boite � 0pt de hauteur�\idx*\setbox\idx*\vsplit�
\restoreparam
\setbox1=\vbox{\unvbox1}% redonner � la boite sa hauteur d'origine�\idx*\vbox\idx*\unvbox�

\edef\intersplitspace{\the\dimexpr\htbefore-(\vdim0+\vdim1)\relax}%�\idx*\the\idx*\dimexpr�*\vdim�
Boites 1+0 : \vbox{%�\idx*\vbox�
       \offinterlineskip% annule le ressort d'interligne�\idx*\offinterlineskip�
       \box1 % affiche la premi�re ligne�\idx*\box�
       \vskip\intersplitspace\relax% ajoute le ressort perdu � la coupure�\idx*\vskip�
       \box0 % affiche les lignes restantes�\idx*\box�
}/

Ici encore, \eTeX{} offre des primitives pr�cieuses qui vont rendre la t�che pr�c�dente plus simple\footnote{Lire le manuel de \eTeX, chapitre �3.11 Discarded Items�.}. La primitive \idx\savingvdiscards a vocation � contenir un entier qui, s'il est positif, autorise la sauvegarde des �l�ments ignor�s lors d'une coupure verticale (les \idx\kern, les ressorts verticaux et les \idx{p�nalit�}s), qu'elle soit une coupure de page ou une coupure de boite verticale par \idx\vsplit. On peut ensuite ins�rer ces �l�ments dans une liste verticale avec \idx\pagediscards pour les �l�ments ignor�s lors d'une coupure de page et avec \idx\splitdiscards pour ceux ignor�s lors d'une coupure par \idx\vsplit. Ces deux listes d'�l�ments sauvegard�s sont vid�es apr�s la routine de sortie ou au d�but de l'op�ration \idx\vsplit. Elles sont �galement vid�es apr�s avoir �t� utilis�es.

Les macros \verb|\totalht| et \verb|\intersplitspace| du code pr�c�dent deviennent d�s lors inutiles :

\showcode/\setbox0=\vbox{%�\idx*\vbox\idx*\setbox�
       \hsize=5cm Ceci est un texte sans aucun int�r�t dont le seul but est�\idx*\hsize�
       de meubler la page de fa�on artificielle.
}

Boite 0 : \copy0 % affiche la boite totale�\idx*\copy�
\medbreak�\idx*\medbreak�

\edef\restoreparam{%
       \vfuzz=\the\vfuzz\relax% sauvegarde le \vfuzz�\idx*\the\idx*\vfuzz�
       \splittopskip=\the\splittopskip\relax% , le \splittopskip�\idx*\splittopskip�
       \savingvdiscards=\the\savingvdiscards\relax% et le \savingvdiscards
       }%
\vfuzz=\maxdimen% annule les avertissements pour d�bordement�\idx*\vfuzz\idx*\maxdimen\idx*{message d'avertissement}�
\splittopskip=0pt % ne rajouter aucun espace au sommet de la boite restante�\idx*\splittopskip�
\savingvdiscards=1 % autorise la sauvagarde des �l�ments supprim�s�\idx*\savingvdiscards�
\setbox1=\vsplit0 to 0pt % couper la boite � 0pt de hauteur�\idx*\setbox\idx*\vsplit�
\setbox1=\vbox{\unvbox1}% redonner � la boite sa hauteur d'origine�\idx*\setbox\idx*\unvbox\idx*\vbox�
\restoreparam

Boites 1+0 : \vbox{%
       \offinterlineskip% annule le ressort d'interligne�\idx*\offinterlineskip�
       \box1 % affiche la premi�re ligne�\idx*\box�
       \splitdiscards% affiche les �l�ments ignor�s�\idx*\splitdiscards�
       \box0 % affiche les lignes restantes�\idx*\box�
}/

Maintenant que la m�thode pour couper \emph{une} ligne a �t� expos�e, il est facile de construire une macro r�cursive qui coupera successivement les lignes jusqu'� ce qu'il n'y ait plus rien � couper. Ceci sera fait par la macro �\numlines :

\centrecode-\numlines<texte � couper en lignes>\endnumlines-

Nous voulons manipuler chaque ligne ainsi coup�e, c'est-�-dire avoir la possibilit� d'�crire quelque chose � droite et � gauche de chaque ligne, tout en ayant �galement le contr�le sur la ligne elle-m�me. Nous allons donc �crire trois macros :

\begin{enumerate}
       \item les macros �\leftline et �\rightline, de syntaxe

       \centrecode-\leftline[<dimension>]{<mat�riel>}
\rightline[<dimension>]{<mat�riel>}-

       \noindent qui stockent dans des macros priv�es le \verb|<mat�riel>| � �crire � gauche et � droite de chaque ligne. Ce \verb|<mat�riel>| sera compos� dans une \idx\hbox de longueur \verb|<dimension>| et dont le ressort \idx\hss sera correctement positionn� pour le contenu s'�tende � gauche ou � droite en d�bordement;
       \item une macro �\formatline dont l'argument \verb|#1| sera la boite contenant la ligne en cours. Par d�faut, \verb|\formatline| sera rendue \verb|\let|-�gale � �\identity pour afficher chaque ligne telle quelle. Il sera possible de personnaliser l'affichage en �crivant, par exemple, \verb|\let\formatline=\frbox| pour encadrer chaque ligne.
\end{enumerate}

Chaque ligne sera enferm�e dans une \idx\hbox afin que le mode vertical principal perdure. Apr�s cette \idx\hbox, \idx\splitdiscards sera ins�r�e. Ainsi, une ligne sera compos�e de la fa�on suivante :

\centrecode-\hbox{%
       \hbox to<dimension gauche>{\hss<mat�riel gauche>}%
       \formatline{<ligne courante>}%
       \hbox to <dimension droite>{<mat�riel droit>\hss}%
}%
\splitdiscards-

Ins�rer \idx\splitdiscards dans la liste verticale principale nous emp�che de savoir quelle est la dimension verticale totale de la ligne compos�e. Certes, nous aurions pu placer le tout dans une \idx\vbox et stocker cette boite un registre pour acc�der � sa dimension verticale. Mais agir ainsi et enfermer \idx\splitdiscards aurait emp�ch� le mat�riel contenu dans \idx\splitdiscards de disparaitre aux coupures de page.

Pourtant, acc�der � la dimension verticale totale de la ligne compos�e peut s'av�rer n�cessaire pour correctement dimensionner les mat�riels affich�s � droite et � gauche de la ligne courante pour obtenir certains effets. Nous allons donc agir comme au code de la page~\pageref{recup.espace.vertical} et calculer \verb|\htbefore| pour obtenir la hauteur de \idx\splitdiscards dans \verb|\intersplitspace|.

Comme le sugg�re son nom, la macro �\numlines a pour vocation premi�re � num�roter les lignes du \verb|<texte>| qui s'�tend jusqu'� \verb|\endnumlines|. Pour ce faire, un compteur \verb|\linecnt| est cr�� et incr�ment� � chaque ligne. Il appartient � l'utilisateur d'afficher, s'il le souhaite, la valeur de ce compteur � l'aide de �\leftline ou �\rightline.

\showcode|\catcode`@11
\newbox\remainbox% boite contenant le texte total�\idx*\newbox�
\newbox\currentline% boite contenant le ligne en cours�\idx*\newbox�
\newcount\linecnt% compteur pour num�roter les lignes�\idx*\newcount�

\def\vdim#1{\dimexpr\ht#1+\dp#1\relax}% hauteur totale de la boite #1��*\vdim\idx*\dimexpr\idx*\ht\idx*\dp�

\newmacro\leftline[0pt]{% d�finit ce qui se trouve � gauche de chaque ligne��*\newmacro�*\leftline�
       \def\wd@left{#1}%
       \def\stuff@left
}

\newmacro\rightline[0pt]{% d�finit ce qui se trouve � droite de chaque ligne��*\newmacro�*\rightline�
       \def\wd@right{#1}%
       \def\stuff@right
}

\let\formatline=\identity% par d�faut, afficher chaque ligne telle quelle��*\identity�

% Par d�faut :
\leftline[11pt]{$\scriptscriptstyle\number\linecnt$\kern3pt }% num�rotation � gauche�\idx*\scriptscriptstyle�*\leftline�
\rightline{}% rien � droite��*\rightline�

\def\numlines{%��*\numlines�
       \par\smallskip�\idx*\smallskip�
       \begingroup% dans un groupe semi-simple
               \splittopskip=0pt % ne rajouter aucun espace au sommet de la boite restante�\idx*\splittopskip�
               \linecnt=0 % initialiser le compteur de lignes
               \savingvdiscards=1 % autorise la sauvagarde des �l�ments supprim�s�\idx*\savingvdiscards�
               \setbox\remainbox=\vbox\bgroup% compose la boite...�\idx*\setbox\idx*\vbox\idx*\bgroup�
                       \advance\hsize by% diminuer la \hsize�\idx*\advance\idx*\hsize�
                       -\dimexpr\wd@left+\wd@right\relax% de la largeur des contenus�\idx*\dimexpr�
}

\def\endnumlines{%
       \egroup�\idx*\egroup�
       \offinterlineskip�\idx*\offinterlineskip�
       \split@line
}

\def\split@line{%
       \ifvoid\remainbox% si la boite est vide�\tidx*{ifvoid}�
               \par% fin du processus
               \endgroup% fermer le groupe ouvert au d�but
       \else% sinon
               \advance\linecnt 1 % incr�mente le compteur de lignes�\idx*\advance�
               \edef\htbefore{\the\vdim\remainbox}%�\idx*\the �*\vdim�
               \edef\restorevfuzz{\vfuzz=\the\vfuzz\relax}% sauvegarde le \vfuzz�\idx*\vfuzz�
               \vfuzz=\maxdimen% annule les avertissements pour d�bordement�\idx*\maxdimen\idx*{message d'avertissement}\idx*\vfuzz�
               \setbox\currentline=\vsplit\remainbox to 0pt % couper la boite � 0pt de hauteur�\idx*\setbox\idx*\vsplit�
               \restorevfuzz
               \setbox\currentline=\vbox{\unvbox\currentline}% redonner � la boite sa hauteur�\idx*\setbox\idx*\unvbox�
               \edef\intersplitspace{% calcul de l'espace vertical perdu � la coupure
                       \the\dimexpr\htbefore-(\vdim\remainbox+\vdim\currentline)\relax�\idx*\the\idx*\dimexpr �*\vdim�
               }%
               \hbox{% en mode vertical et dans une hbox, afficher :�\idx*{mode!vertical}�
                       \hbox to\wd@left{\hss\stuff@left}%   1) ce qui est � gauche�\idx*\hss\idx*\hbox�
                       \formatline{\box\currentline}%       2) la ligne courante�\idx*\box�
                       \hbox to\wd@right{\stuff@right\hss}% 3) ce qui est � droite�\idx*\hss�
               }%
               \splitdiscards% affiche ce qui a �t� ignor� � la coupure�\idx*\splitdiscards�
               \expandafter\split@line% recommencer
       \fi
}

\def\dummytext#1{%
       \for\xx=1to#1\do% composer #1 fois la phrase suivante :��*\for�
               {Ceci est un texte sans aucun int�r�t dont le seul but est de meubler
               la page de fa�on artificielle. }%
}

\catcode`@12
\parindent=2em �\idx*\parindent�

ESSAI 1 :
��*\numlines�\numlines
       \dummytext{2}\par% 2 phrases
       $$1+1=2$$\par% des maths
       \dummytext{1}\par% une phrase
       \hrulefill\par% un leaders�\idx*\hrulefill�
       \dummytext{2}% 2 phrases
       \hrule height2pt depth 2pt %une \hrule�\idx*\hrule�
       \vskip10pt % saute 10pt verticalement�\idx*\vskip�
       \dummytext{1}% une phrase
\endnumlines\medbreak�\idx*\medbreak�

ESSAI 2 :
\leftline{}\rightline{}% rien � gauche et rien � droite��*\leftline�
\frboxsep=-\frboxrule% encadrer vers "l'int�rieur"��*\frboxsep�*\frboxrule�
\let\formatline\frbox% lignes encadr�es��*\frbox�
��*\numlines�\numlines
       \dummytext{4}
\endnumlines\medbreak�\idx*\medbreak�

ESSAI 3 :
\let\formatline\identity��*\identity�
\leftline[7pt]{%��*\leftline�
       \for\xx= 1 to 2 \do{% ins�rer 2 fois�\idx*\llap �*\for�
               \setbox0=\hbox{% % mettre dans une \hbox une \vrule de "bonnes dimensions"�\idx*\setbox\idx*\hbox�
                       \vrule height\ht\currentline depth\dimexpr\dp\currentline+\intersplitspace
                              width0.5pt }%�\idx*\vrule\idx*\dimexpr\idx*\dp�
               \dp0=\dp\currentline% r�ajuster la profondeur (c-�-d enlever \intersplitspace)�\idx*\dp�
               \box0 % afficher le boite�\idx*\box�
               \kern2pt % et ins�rer un espace horizontal de 2pt apr�s chaque r�glure verticale�\idx*\kern�
               }%
       \kern2pt % ajouter 2pt de plus entre les lignes et le texte�\idx*\kern�
}

\rightline[10pt]{\kern5pt $\scriptscriptstyle\number\linecnt$}% num�roter � droite�\idx*\scriptscriptstyle�*\rightline�

��*\numlines�\numlines
       \dummytext{2}

       $$a^2+b^2=c^2$$

       \dummytext{2}
\endnumlines|
� l'essai \no3,  une petite cuisine interne est faite pour tracer deux traits verticaux � gauche du texte. Elle consiste � afficher deux fois un trait vertical de bonnes dimensions. Pour ce faire, le registre de boite \no0 re�oit une \idx\hbox contenant une r�glure dont la hauteur co�ncide exactement avec celle de la ligne en cours et dont la profondeur couvre aussi l'espace additionnel \verb|\intersplitspace| qui s�pare deux lignes adjacentes. Cette \idx\hbox est ensuite redimensionn�e pour qu'elle ait la dimension verticale de la ligne � afficher. En proc�dant ainsi, les r�glures seront jointives d'une ligne � l'autre.

Pour arriver au m�me r�sultat, nous aurions pu inclure une \idx\hrule de m�me dimensions que la \idx\vrule de l'essai \no3 dans une \idx\vtop dont la dimension verticale est impos�e et �gale � la hauteur totale de la ligne � afficher. Le d�bordement vers le bas, d'une valeur de \verb|\intersplitspace| serait rattrap� par un \idx\vss. Voici donc un code �quivalent qui ne mobilise pas de registre de boite :

\centrecode-\leftline[7pt]{%��*\leftline�
       \for\xx= 1 to 2 \do{% ins�rer 2 fois��*\for�
               \vtop to\dimexpr\ht\currentline+\dp\currentline{%�\idx*\vtop\idx*\ht\idx*\dp�
                       \hrule height\ht\currentline
                              depth\dimexpr\dp\currentline+\intersplitspace�\idx*\dp�
                              width0.5pt
                       \vss% rattrape la profondeur de trop \intersplitspace�\idx*\vss�
                       }%
               \kern2pt % et ins�rer un espace horizontal
                        % de 2pt apr�s chaque r�glure verticale�\idx*\kern�
       }%
       \kern2pt % ajouter 2pt de plus entre les lignes et le texte�\idx*\kern�
}-

\section{�tirer horizontalement du texte}\idx*[|(]{�tirer du texte}
Il tout d'abord faut �tre pr�cis sur les termes. �tirer du texte va signifier ici que des espaces seront ins�r�es entre chaque lettre de fa�on � ce que le texte ainsi modifi� prenne davantage de place que s'il �tait compos� normalement.

Il faut �galement savoir qu'�tirer du texte est un effet typographiquement discutable qui donne parfois des r�sultats malheureux. Il est donc recommand� de ne pas en abuser et de limiter sa port�e � des portions de texte \emph{courtes}, par exemple pour mettre en �vidence des titres, cas o� son emploi est justifi�.

\subsection{Espace inter-lettre}
La m�thode qui semble �tre la plus naturelle est d'ins�rer un ressort pr�d�fini que nous appellerons � inter-lettre � apr�s chaque caract�re dont le catcode est 11 ou 12 et en rempla�ant l'espace par un ressort � inter-mot � dont la dimension fixe sera plus importante que celles des ressorts inter-lettres. La macro �\spreadtxt\verb|{<texte>}| s'acquittera de cette t�che.

La macro �\parse �crite � la page~\pageref{parse} permet de lire le texte token par token et d'agir en cons�quence via la macro �\testtoken. Nous nous contenterons donc de modifier localement �\testtoken pour lui faire ins�rer les espaces voulues. La macro �\spreadtxt se chargera de lire son argument, d'ouvrir un groupe semi-simple, de correctement d�finir �\testtoken et appellera �\parse :

\showcode/% d�finition des ressorts "inter-lettre" et "inter-mot"
\newskip\interletterskip \interletterskip=0.25em plus0.05em minus0.05em �\idx*\newskip�
\newskip\interwordskip   \interwordskip=3\interletterskip\catcode`\@11 �\idx*\newskip�
\catcode`@11
\def\spreadtxt@testtoken#1{% macro qui teste le token��*\testtoken�
       \ifcat\noexpand#1\sptoken% si le token est un espace�\defline\aaa\tidx*{ifcat}\idx*\noexpand�*\sptoken�
               \parseadd{%
                       \unskip% retirer le pr�c�dent ressort�\idx*\unskip�
                       \hskip\interwordskip}% et ajouter le ressort inter-mot�\idx*\hskip�
       \else
               \ifcat\noexpand#1a% si le token est une lettre�\defline\bbb\tidx*{ifcat}�
                       \parseadd{#1\hskip\interletterskip}% ajouter le ressort inter-lettre�\idx*\hskip�
               \else
                       \ifcat\noexpand#1.% si le token est "autre", comme le "."�\defline\ccc\tidx*{ifcat}\idx*\noexpand�
                               \parseadd{#1\hskip\interletterskip}% ajouter le ressort inter-lettre�\idx*\hskip�
                       \else% sinon
                               \parseadd{#1}% ajouter le token lu�\defline\ddd�
                       \fi
               \fi
       \fi
       \parse@i
}
\def\spreadtxt{%
       \ifstarred% si �toil�e
               {\spreadtxt@i{\parse*}}% appeler \parse*��*\parse�
               {\spreadtxt@i{\parse}}% sinon, appeler \parse��*\parse�
}
\def\spreadtxt@i#1#2{% #1= appel "\parse*" ou "\parse"   #2 = texte � espacer
       \begingroup% dans un groupe
               \let\testtoken=\spreadtxt@testtoken% modifier \testtoken
               #1#2\parsestop% et appeler \parse
       \endgroup
}
\catcode`@12

\spreadtxt{Comme on le voit sur cet exemple, une espace est ins�r�e apr�s
{\it chaque} caract�re de catcode 10, 11 ou 12.}�\idx*\it\idx*{catcode!10\space(espace)}�
\medbreak�\idx*\medbreak�

\spreadtxt*{Comme on le voit sur cet exemple, une espace est ins�r�e apr�s
{\it chaque} caract�re de catcode 10, 11 ou 12.}�\idx*\it�/

Il y a un petit dysfonctionnement tout de m�me : les caract�res accentu�s ne sont pas suivis d'une espace. Ceci s'explique par le fait que ce livre a �t� compos� avec \LaTeX{} et l'extension \texttt{inputenc} charg�e avec l'option \latin. La combinaison des deux rend les caract�res accentu�s actifs et donc les tests des lignes \nos\aaa, \bbb{} et \ccc{} sont faux. Le token est donc simplement rajout� au registre de tokens � la ligne \no\ddd{} sans le ressort inter-lettre. Il y a plusieurs fa�ons de se sortir de ce mauvais pas. On pourrait imaginer un test suppl�mentaire o� l'on traiterait un caract�re actif comme un caract�re normal et ins�rerait le ressort inter-lettre apr�s lui. Mais cette m�thode �chouerait avec \utf et un moteur 8 bits\idx*{moteur!8 bits}, car si l'on rencontre un caract�re cod� sur plusieurs octets, le premier octet (actif) sera s�par� des autres octets participant � la construction du caract�re final.

On touche du doigt une difficult� majeure, celle de lire un texte caract�re par caract�re, o� le mot � caract�re � est pris au sens d'entit� typographique. La difficult� d�pend de la combinaison entre l'\idx{encodage} du code source et le type de moteur utilis� :

\begin{description}
       \item[cas favorables] Les associations entre un moteur et un \idx{encodage} sur un nombre d'octets correspondant � ce que lit le moteur ne pr�sentent aucune difficult� puisque les caract�res typographiques sont les entit�s lues par le moteur.
       \begin{itemize}[topsep=0pt]
               \item \idx*{moteur!8 bits}moteur 8 bits (comme \verb|tex|, \verb|etex| et \verb|pdftex|) avec un \idx{encodage} 8 bits (comme \latin) : les caract�res lus sont des \idx{octet}s;
               \item \idx*{moteur!utf8}moteur \utf (comme \verb|xetex| et \verb|luatex|) avec un encodage \utf : les caract�res lus sont des caract�res \utf;
       \end{itemize}
       \item[cas d�favorables] Les combinaisons entre un moteur 8 bits\idx*{moteur!8 bits} et un encodage multi octets comme \utf va faire surgir de grandes difficult�s pour lire le code source caract�re \utf par caract�re \utf.
\end{description}

\subsection{Liste de motifs ins�cables}
Comment s'en sortir sans laisser de c�t� le cas le plus d�favorable qui est encore tr�s utilis�\footnote{L'association de pdf\TeX{} (ou pdf\LaTeX) avec un encodage \utf est en effet tr�s r�pandu. Cette combinaison ouvre la possibilit� d'�crire dans le code source beaucoup plus de caract�res que ceux accessibles avec un \idx{encodage} 8 bits et fonctionne tr�s bien sauf lorsqu'on souhaite �laborer des \emph{programmes} devant lire le code source caract�re par caract�re.} ? L'id�e est de cr�er une liste de motifs indivisibles qui seraient laiss�s tels quels : il faudrait donc tester � chaque it�ration si les prochains caract�res � lire ne commencent pas par un des motifs. Dans l'affirmative, il faudrait laisser ce motif et ins�rer le ressort inter-lettre apr�s ce motif. Si le test s'av�rait n�gatif, il faudrait agir comme pr�c�demment.

Le probl�me est que pour d�terminer si ce qui reste � lire commence par un motif, il faut lire la totalit� du texte � espacer au pr�alable. La m�thode change donc radicalement. Il ne s'agit plus de laisser �\parse faire le travail. Nous allons cr�er une nouvelle macro �\spacetxt qui reprendra en grande partie l'algorithme vu pour la macro �\substitute (voir page~\pageref{substitute}). Le principe consiste � stocker la totalit� du texte initial dans la macro \verb|\spacetxt@code| et le texte espac� dans le registre de tokens \verb|\spacetxt@toks|. Au fur et � mesure des it�rations, \verb|\spacetxt@code| sera peu � peu amput�e des caract�res lus et \verb|\spacetxt@toks| collectera le code produisant le texte espac�.

La liste des motifs indivisibles sera stock�e dans la macro \verb|\indivilist|, chacun �tant s�par� du suivant par une virgule. Pour tenir compte de ces motifs, il faudra � chaque it�ration et avant toute chose, tester si le texte de remplacement de \verb|\spacetxt@code| commence par un des motifs d�clar�s dans \verb|\indivilist|. Cette s�rie de tests sera faite � l'aide d'une boucle de type �\doforeach. Il est clair que tous ces tests suppl�mentaires vont �tre ex�cut�s � chaque it�ration et cela consommera du temps; ce n'est donc pas une panac�e du point de vue de l'efficacit� du programme. Heureusement, comme le texte � espacer est cens� �tre assez court et le nombre de motifs ne doit normalement pas exc�der une dizaine d'�l�ments, la perte de temps n'est pas tr�s importante. Nous utiliserons la macro �\doforeachexit pour sortir pr�matur�ment de la s�rie de tests si l'un est positif et le bool�en \verb|\if@indivifound| sera pris �gal � \verb|vrai| pour indiquer qu'un motif a �t� trouv�. Dans ce cas, nous retirerons ce motif � \verb|\spacetxt@code| pour l'ajouter � \verb|\spacetxt@toks| en le faisant suivre de l'espace inter-lettre.

La fin du processus se produit lorsqu'il n'y a plus de texte � espacer, c'est-�-dire lorsque \verb|\spacetxt@code| est vide.

Pour espacer du texte entre accolades, la \idx{macro �toil�e} �\spacetxt\verb|*| devra �tre appel�e. Les m�mes astuces de programmation que pour la macro �\substitute ont �t� employ�es.\label{spacetxt}

\showcode/\newskip\interletterskip�\idx*\newskip�
\newskip\interwordskip �\idx*\newskip�
\catcode`\@11
\newtoks\spacetxt@toks%  le registre qui contient le texte final�\idx*\newtoks�

\def\spacetxt{%��*\spacetxt�
       \let\spacetxt@endprocess\spacetxt@endnormal
       % d�finit la macro appel�e en fin de processus -> a priori : fin normale
       \ifstarred% si la macro est �toil�e��*\ifstarred�
               {\let\spacetxt@recurse\spacetxt@star% d�finir la macro r�cursive
               \spacetxt@i% et aller � \spacetxt@i
               }% sinon
               {\let\spacetxt@recurse\spacetxt@nostar% d�finir la macro r�cursive
               \spacetxt@i% et aller � \spacetxt@i
               }%
}

\newmacro\spacetxt@i[0.3em plus0.07em minus.07em][3\interletterskip]1{%��*\newmacro�
% arg optionnel #1 et #2 = ressorts inter-lettre et inter--mot
% #3 = texte � espacer
       \interletterskip=#1\relax
       \interwordskip=#2\relax
       \def\spacetxt@code{#3}% met le texte � espacer dans \spacetxt@code
       \spacetxt@toks{}% initialiser le registre contenant le texte final
       \spacetxt@recurse% aller � la macro r�cursive pr�c�demment d�finie
}

\newif\if@indivifound% bool�en qui sera vrai si un motif sp�cial est rencontr�\idx*\newif�

\def\rightofsc#1#2{%
       \exparg\ifin{#1}{#2}% si #1 contient le #2
               {\def\right@of##1#2##2\@nil{\def#1{##2}}%
               \expandafter\right@of#1\@nil% appelle la macro auxiliaire
               }%
               {\let#1=\empty}% sinon, #1 est vide
}

\def\spacetxt@nostar{%
       \exparg\ifempty{\spacetxt@code}% si texte restant est vide��*\exparg �*\ifempty�
               \spacetxt@endprocess% aller � la fin du processus
               {\@indivifoundfalse% sinon, a priori, les motifs non r�guliers ne sont pas trouv�s
               % pour chaque \indivi@tmp dans \indivilist
               \expsecond{\doforeach\indivi@tmp\in}{\indivilist}% pour chaque motif indivisible��*\expsecond �*\doforeach�
                       {% si le code commence par le motif courant
                       \exptwoargs\ifstartwith\spacetxt@code\indivi@tmp��*\exptwoargs �*\ifstartwith�
                               {% l'ajouter dans le registre ainsi que l'espace inter-lettre
                               \eaddtotoks\spacetxt@toks{\indivi@tmp\hskip\interletterskip}%��*\eaddtotoks\idx*\hskip�
                               % et enlever le motif du texte restant � lire
                               \expsecond{\rightofsc\spacetxt@code}{\indivi@tmp}%��*\expsecond �*\rightofsc�
                               \@indivifoundtrue% marquer qu'un motif a �t� trouv�
                               \doforeachexit% et sortir pr�matur�ment de la boucle��*\doforeachexit�
                               }%
                               \relax% si le code ne commence pas le motif courant -> ne rien faire
                       }%
               \unless\if@indivifound% si aucun motif n'a �t� trouv�\tidx*{unless}�
                       \grab@first\spacetxt@code\spacetxt@temp% retirer le 1er caract�re du texte
                       \ifx\spacetxt@temp\space% si le 1er caract�re est un espace�\idx*\space�
                               \addtotoks\spacetxt@toks{%��\addtotoks�
                                       \unskip% annuler le pr�c�dent ressort�\idx*\unskip�
                                       \hskip\interwordskip}% ajouter l'espace inter-mot au registre de token�\idx*\hskip�
                       \else% si le 1er caract�re n'est pas un espace
                               % ajouter ce caract�re et l'espace inter-lettre au registre de token
                               \eaddtotoks\spacetxt@toks{\spacetxt@temp\hskip\interletterskip}%��*\eaddtotoks�
                       \fi
               \fi
               \spacetxt@recurse% enfin, continuer le processus
               }%
}

\def\spacetxt@star{%
       \exparg\ifempty{\spacetxt@code}% si texte restant est vide��*\exparg �*\ifempty�
               \spacetxt@endprocess% aller � la fin du processus
               {% sinon, si texte commence par "{"
               \exparg\ifbracefirst{\spacetxt@code}%��*\exparg �*\ifbracefirst�
                       {\grab@first\spacetxt@code\spacetxt@temp
                       % mettre {<argument} dans \spacetxt@temp
                       \begingroup% ouvrir un groupe
                       % mettre le contenu de l'argument dans \spacetxt@code
                       \expandafter\def\expandafter\spacetxt@code\spacetxt@temp
                       \let\spacetxt@endprocess\spacetxt@endingroup% changer le processus de fin
                       \spacetxt@toks{}% initialiser
                       \spacetxt@recurse% ex�cuter le processus avec ce nouveau texte
                       }% si le code ne commence pas par "{", aller � \spacetxt@nostar mais comme
                       \spacetxt@nostar% \spacetxt@recurse vaut \spacetxt@star, n'y faire qu'1 boucle
               }%
}

\def\spacetxt@endnormal{% fin de processus normal
       \the\spacetxt@toks% afficher le registre � token�\idx*\the�
       \unskip% et supprimer le dernier ressort�\idx*\unskip�
}

\def\spacetxt@endingroup{% fin du processus dans un groupe :
       \expandafter\endgroup\expandafter% avant de fermer le groupe
       \addtotoks\expandafter\spacetxt@toks\expandafter% ajouter au registre hors du groupe��*\addtotoks�
               {\expandafter{\the\spacetxt@toks}}% ce qui est collect� localement mis entre {}�\idx*\the�
       \spacetxt@recurse% puis aller � la macro r�cursive
}

\catcode`\@12
\def\indivilist{�,�}% liste des motifs sp�ciaux
\spacetxt*{Comme on le voit sur cet exemple, une espace est ins�r�e apr�s
{\it chaque} caract�re.}��*\spacetxt\idx*\it�
\medbreak�\idx*\medbreak�

\def\indivilist{�,es,au,<<,>>}
\spacetxt[4pt plus.7pt minus.7pt][12pt plus2pt minus2pt]{Ici, les motifs <<es>> et <<au>>
restent indivisibles et la ligature des guillemets devient possible en d�clarant "<<" et
">>" comme motifs.}��*\spacetxt\idx*\it�/

Nous avons utilis� les arguments optionnels de la macro \verb|\spacetxt@i| pour d�finir � l'int�rieur de celle-ci les ressorts inter-lettre et inter-mot. Cette m�thode est pr�f�rable � celle de �\spreadtxt o� l'on avait d�fini ces registres de ressort en dehors de toute macro. En effet, si l'on d�finit ces ressorts avec des unit�s qui varient selon le contexte (comme l'\idx*{unit�!ex}\verb|ex| ou l'\idx*{unit�!em}\verb|em|), les dimensions des ressorts ainsi d�finis ne d�pendront que de la valeur de ces unit�s \emph{lors de l'assignation}.

Il est important de comprendre que l'\idx*{assignation!registre de ressort}assignation d'une dimension � un registre de ressort (ou de dimension) \emph{�value} cette dimension pour la stocker dans le registre. La diff�rence est fondamentale entre

\centrecode-<ressort>=0.3em-

\noindent et

\centrecode-\def\<macro>{0.3em}-

\noindent suivi plus tard de

\centrecode-<ressort>=\<macro>-

En effet, lorsqu'on �crit �\verb|<ressort>=0.3em|�, la dimension \verb|3em| est �valu�e et le r�sultat est stock� dans le registre qui d�s lors, contient une dimension qui d�pend de la valeur de l'\verb|em| lors de l'assignation.

Au contraire, �crire �\verb|\def\<macro>{0.3em}|� stocke simplement dans le texte de remplacement de \verb|\<macro>| les caract�res �\verb|0.3em|�. C'est lors de l'assignation de ressort �\verb|<ressort>=\<macro>|� que l'�valuation de \verb|0.3em| est faite. Ce passage par une macro auxiliaire de stockage permet donc de garder le caract�re variable de l'unit� \verb|em| et choisir le moment o� l'on �value cette dimension.

\subsection{Une alternative � \texttt{\char`\\litterate}}
La m�thode pr�c�dente peut �tre adapt�e pour ins�rer un court passage en fonte � chasse fixe � l'int�rieur d'un paragraphe, pour �crire une adresse URL, par exemple. Nous allons �crire une macro �\ttcode, de syntaxe

\centrecode-\ttcode<d�limiteur><texte><d�limiteur>-

\noindent qui compose le \verb|<texte>| en police � chasse fixe o� les tokens de catcode diff�rents de 10, 11 et 12 sont neutralis�s avec \idx\dospecials. En invoquant �\spacetxt, nous allons ins�rer un ressort de faible dimension apr�s chaque token du \verb|<texte>| et donc, contrairement � �\litterate, �\ttcode permet qu'une coupure se produise apr�s chaque token du \verb|<texte>|.

\showcode|\catcode`\@11
\def\ttcode#1{% lit #1, le <d�limiteur> de d�but��*\ttcode�
       \def\ttcode@i##1#1{% ##1 = <texte> entre d�limiteurs
               \tt% passe en fonte � chasse fixe�\idx*\tt�
               \setbox0=\hbox{ }%�\idx*\setbox\idx*\hbox�
               \edef\spc@wd{\the\wd0 }% longueur d'un espace�\idx*\the\idx*\wd�
               \spacetxt��*\spacetxt�
                       [.1pt plus0pt minus.1pt]% espace inter-lettre
                       [\glueexpr\wd0+.3pt plus.1pt minus.1pt\relax]% espace inter-mot�\idx*\glueexpr\idx*\wd�
                       {##1}% le <texte> est compos� par \spacetxt
               \endgroup
       }%
       \begingroup
               \def\indivilist{<<,>>,{,,},--}% (rajouter �, �, �, etc. en codage UTF8)
               \def\do##1{\catcode`##1=12 }%�\idx*\do�
               \dospecials% rend inoffensifs tous les tokens sp�ciaux�\idx*\dospecials�
               \letactive\ =\space % rend l'espace actif��*\letactive�
               \ttcode@i% va lire le <texte> et le d�limiteur de fin
}
\catcode`\@12

\hfill\vrule\vbox{%�\idx*\hfill\idx*\vrule\idx*\vbox�
       \hsize=.75\hsize�\idx*\hsize�
       Avec \ttcode/\ttcode/, on peut ins�rer une adresse internet <<
       \ttcode-http://www.gutenberg.eu.org/Typographie- >> puis repasser en fonte normale
       puis \ttcode+m�me composer un court passage en fonte � chasse fixe -- m�me si les
       coupures de mots se font n'importe o� -- et aussi afficher tous les caract�res
       sp�ciaux <<{$^ _$#}&+>>, et finir en fonte normale\ldots
}\vrule\hfill\null�\idx*\hfill\idx*\vrule\idx*\null�*\ttcode�|\idx*[|)]{�tirer du texte}

\section{Composition en fonte � chasse fixe}\idx*[|(]{composition en fonte � chasse fixe}
\subsection{Mise en �vidence du probl�me}
Une \idx{fonte}\footnote{On peut souvent confondre police et fonte, mais une diff�rence s�mantique existe. Une \emph{\idx{police}} est un ensemble de glyphes qu'un auteur (bien souvent, c'est le m�me auteur qui dessine une police enti�re) a dessin� dans un m�me esprit en respectant le m�me style. Une \emph{\idx{fonte}} est un sous-ensemble d'une police ayant des caract�ristiques bien d�termin�es : taille, graisse (l�ger, normal, demi-gras, gras, etc.), forme (italique, pench�, petite capitale, etc.)

Par exemple, le texte de ce livre est �crit avec la \emph{\idx{police}} Libertine, mais \textbf{ceci} et \textit{ceci} sont �crits en deux \emph{\idx{fonte}s} diff�rentes de cette police.} est dite � � chasse fixe � lorsque tous ses caract�res ont la m�me largeur, y compris l'espace qui est non �tirable et non comprimable. La composition en fonte de ce type peut poser des probl�mes, car � cause de cette particularit� g�om�trique, il devient impossible de respecter \emph{en m�me temps} les trois contraintes suivantes\label{contraintes.tt} :

\begin{enumerate}
       \item caract�res parfaitement les uns au-dessous des autres d'une ligne � l'autre;
       \item composition justifi�e, c'est-�-dire que la distance entre le bord gauche du premier caract�re et le bord droit du dernier est toujours la m�me;
       \item coupures des mots respect�es ou interdites.
\end{enumerate}
\grandsaut

Il faut savoir que le passage en \idx{fonte} � chasse fixe avec \LaTeX{} � l'aide des macros \idx\texttt ou \idx\ttfamily d�sactive la coupure des mots (nous verrons comment). D�s lors, il suffit qu'un mot assez long se trouve en \idx{fin de ligne} pour que le d�passement dans la marge soit tellement important que parfois, les caract�res se trouvent en dehors de la page physique. Les utilisateurs de \LaTeX{} savent certainement de quoi je parle\ldots

� titre d'exemple, voici un court paragraphe compos� en fonte � chasse fixe (avec la macro \idx\ttfamily) comme le verrait un utilisateur de \LaTeX{} (alors que pour un utilisateur de \TeX{} avec la macro \idx\tt, les coupures de mots seraient effectu�es) :

\showcode[\hfuzz=\maxdimen]|\def\ttwide{0.7}% coefficient pour la largeur de composition
\def\ttindent{5}% nombre de caract�res d'indentation
\hfill\vrule�\idx*\hfill\idx*\vrule�
\vbox{%
       \ttfamily% en TeX, on �crirait "\tt"�\idx*\ttfamily�
       \setbox0\hbox{0}% \wd0 est donc la largeur d'un caract�re�\idx*\setbox�
       \parindent=\ttindent\wd0 % r�glage de l'indentation�\idx*\parindent\idx*\wd�
       \hsize=\ttwide\hsize % compose sur 70% de la largeur�\idx*\hsize�
       Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauches
       et droites du texte ont �t� trac�es, on constate que les caract�res sont
       exactement les uns au-dessous d'une ligne � l'autre. Des d�bordements dans
       la marge deviennent alors in�vitables, car la largeur de composition (ici
       \the\hsize) n'est pas un multiple de la largeur d'un caract�re (\the\wd0 ),�\idx*\the\idx*\hsize\idx*\wd�
       le quotient des deux valant environ
       \xdef\ttratio{\decdiv{\dimtodec\hsize}{\dimtodec\wd0 }}\ttratio.��*\decdiv�*\dimtodec\idx*\wd\idx*\xdef�
}%
\vrule\hfill\null�\idx*\null�|

Bien s�r, le \idx[!log]{fichier} \verb|log| contient 6 avertissements\idx*{message d'avertissement}, chacun informant l'utilisateur que \TeX{} a d� composer une ligne trop longue\idx*{d�bordement de boite} :

\centrecode|Overfull \hbox (4.97778pt too wide) in paragraph at lines 9--16
Overfull \hbox (31.85786pt too wide) in paragraph at lines 9--16
Overfull \hbox (20.33783pt too wide) in paragraph at lines 9--16
Overfull \hbox (43.3779pt too wide) in paragraph at lines 9--16
Overfull \hbox (1.13777pt too wide) in paragraph at lines 9--16
Overfull \hbox (8.8178pt too wide) in paragraph at lines 9--16|

Ici en effet, sur chaque ligne, il entre \def\intratio#1.#2\relax{\def\intratio{#1}}\expandafter\intratio\ttratio\relax\intratio{} caract�res complets. Apr�s ce \intratio\ieme{} caract�re, comme il reste de la place, \TeX{} place le caract�re suivant entrant d�s lors dans un d�passement dans la marge. Les coupures de mots �tant interdites, il continuera � placer des caract�res dans la marge jusqu'au prochain espace qui provoquera, mais trop tard, une coupure de ligne.

Livrons-nous � un petit calcul pour comprendre la valeur \verb|8.8178pt| donn�e pour le d�passement de la sixi�me ligne. Cette ligne comporte 62 caract�res : les \intratio{} complets plus les 3 derni�res lettres du mot �\verb|quotient|�. Le d�passement dans la marge vaut

\[
62\times3.84001-229.26292
\]

\noindent c'est-�-dire \verb|8.8177pt|. C'est bien, � une erreur d'arrondi pr�s, la valeur qui est donn�e par \TeX{} dans le message d'avertissement\idx*{message d'avertissement} du \idx[!log]{fichier} \verb|log|.

\subsection{\Qu elques notions sur les fontes}
Avant d'envisager toute solution concernant les fontes de caract�res, il nous faut entrer un peu plus profond�ment dans les entrailles de \TeX{} afin d'examiner quelques commandes sp�cifiques. Nous nous en tiendrons au strict minimum, car la manipulation des fontes en \TeX{} est un monde long et complexe � explorer.

\subsubsection{Les primitives \texttt{\char`\\font} et \texttt{\char`\\fontname}}\idx*[|(]\fontname
\begin{regle}
La primitive \idx\fontname permet d'acc�der au nom externe d'un fichier de \idx{fonte} selon la syntaxe

\centrecode-\fontname<fonte>-

\noindent o� \verb|<fonte>| est soit une s�quence de contr�le d�finie avec la primitive \idx\font, soit la primitive \idx\font elle-m�me auquel cas on fait r�f�rence � la fonte en cours d'utilisation. Le tout se d�veloppe en le nom du fichier externe correspondant � la \idx{fonte} sp�cifi�e.
\end{regle}

Ainsi, ce paragraphe est �crit avec une des fontes de la \idx{police} �Libertine� dont le nom du fichier externe est �\expandafter\texttt\expandafter{\fontname\font}�. Lorsqu'on passe en fonte grasse, le nom devient �{\bfseries\expandafter}\expandafter\texttt\expandafter{\fontname\font}� tandis qu'avec la fonte italique, le nom est �{\itshape\expandafter}\expandafter\texttt\expandafter{\fontname\font}�.

Lorsqu'une \idx{fonte} est utilis�e dans une autre taille que celle pour laquelle elle a �t� dessin�e, le mot-cl� �\verb|at|� suivi de la taille d'utilisation est ajout� apr�s le nom obtenu :

\begingroup
\showcode|Fonte normale : \fontname\font\par�\idx*\fontname\idx*\font�
{\bf Fonte grasse : \fontname\font\par}�\idx*\bf�
{\it Fonte italique : \fontname\font\par}�\idx*\it�
{\sc Fonte petites majuscules : \fontname\font}�\idx*\sc�|\idx*[|)]\fontname
\endgroup

Le �\verb|at 8.0pt|� exprime que les rendus des codes de ce livre sont compos�s avec une taille de \verb|8pt| impos�e, ce qui revient � dire que les dessins des caract�res ainsi que toutes leurs dimensions g�om�triques ont �t� redimensionn�s pour atteindre cette taille.

\begin{regle}
La primitive \idx\font permet de cr�er une s�quence de contr�le qui, lorsqu'elle sera ex�cut�e, effectuera un changement de fonte. On utilise la syntaxe

\centrecode-\font\<macro>=<nom de fonte> at <dimension>-

\noindent o� �\verb|at <dimension>|� est facultatif.
\end{regle}

Voici comment cr�er des macros (\verb|\gras|, \verb|\ital| et \verb|\itgras|) qui, lorsqu'elles sont appel�es, s�lectionnent respectivement la \idx{fonte} de taille \verb|8pt|, en gras, italique et gras italique :

\showcode/\font\gras=LinLibertineTB-tlf-t1 at 8pt�\idx*\font�
\font\ital= LinLibertineTI-tlf-t1 at 8pt
\font\itgras=LinLibertineTBI-tlf-t1 at 8pt
Du texte normal {\gras puis en gras, \ital en italique,
\itgras en italique gras} et retour � la normale./

\subsubsection{Caract�re de coupure de mots}
Chaque \idx{fonte} se voit assigner un caract�re de coupure qui sera ins�r� � la fin d'une ligne lorsqu'un mot est coup�. Par d�faut, ce caract�re est le tiret �\verb|-|�.

\begin{regle}
Le caract�re ins�r� aux coupures de mots est stock� dans un registre interne de type entier appel� \idx*{caract�re de coupure}\idx\hyphenchar. Ce registre \emph{doit} �tre suivi de la \idx{fonte} � laquelle on souhaite se r�f�rer :

\centrecode-\hyphenchar<fonte>-

On peut � tout moment choisir un autre caract�re de coupure par son code de caract�re en modifiant \idx*{caract�re de coupure}\idx\hyphenchar :

\centrecode-\hyphenchar<fonte>=<code de caract�re>-

Si le \verb|<code de caract�re>| contenu dans \idx*{caract�re de coupure}\idx\hyphenchar est n�gatif ou est sup�rieur � 255, aucun caract�re n'est s�lectionn� et cela d�sactive les coupures de mots.

L'assignation d'un entier � \idx*{caract�re de coupure}\idx\hyphenchar est toujours globale\idx*{assignation!toujours globale}.
\end{regle}

\showcode/Code du caract�re de coupure = \number\hyphenchar\font\par�\idx*\font�
Caract�re de coupure : "\char\hyphenchar\font"/

Voici comment modifier le \idx*{caract�re de coupure}\idx\hyphenchar :

\showcode[\hfuzz=\maxdimen]/\def\longtext{Voici une phrase �crite avec des mots insignifiants mais terriblement,
       �pouvantablement, horriblement et ind�niablement longs.}
% cr��r une macro restaurant le \hyphenchar
\edef\restorehyphenchar{\hyphenchar\font=\number\hyphenchar\font}%�\idx*\hyphenchar\idx*\font�

%comportement normal, caract�re de coupure "-"
1) \vrule\vbox{\hsize=5cm \longtext}\vrule\hfill�\idx*\vrule\idx*\vbox\idx*\hsize\idx*\hfill�
% modification du caract�re de coupure "W"
2) \vrule\vbox{\hsize=5cm \hyphenchar\font=`W \longtext}\vrule�\idx*\hyphenchar�
\medbreak�\idx*\medbreak�
% interdiction des coupures de mots
3) \vrule\vbox{\hsize=5cm \hyphenchar\font=-1 \longtext}\vrule�\idx*\hyphenchar\idx*\font\idx*\vrule�
\restorehyphenchar/

Lorsque la largeur de la composition est faible, interdire les coupures peut conduire \TeX{} � composer des lignes trop ou pas assez remplies. La macro de \LaTeX{} \idx\sloppy rel�che certains param�tres de composition de \TeX{} de telle sorte que les d�bordements dans les marges sont presque toujours �vit�s, au prix d'espaces inter-mots parfois tr�s (trop !) larges. C'est pourquoi elle ne doit �tre utilis�e qu'en ultime recours.

\showcode[\hbadness=10000 ]/\def\longtext{Voici une phrase �crite avec des mots insignifiants mais terriblement,
       �pouvantablement, horriblement et ind�niablement longs.}

\edef\restorehyphenchar{\hyphenchar\font=\number\hyphenchar\font}%�\idx*\hyphenchar\idx*\font�
\vrule\vbox{\hsize=5cm \hyphenchar\font=-1 \sloppy \longtext}\vrule�\idx\hsize\idx*\hyphenchar\idx*\font\idx*\sloppy�
\restorehyphenchar/

Les utilisateurs de \LaTeX{}, � qui s'adresse le code ci-dessous, doivent donc savoir que lorsqu'ils passent en \idx{fonte} � chasse fixe (avec la macro \idx\ttfamily ou \idx\texttt), le code du \idx{caract�re de coupure} vaut $-1$. Les coupures de mots sont d�s lors interdites.

\showcode/a) \texttt{\number\hyphenchar\font}\qquad�\idx*\texttt\idx*\number\idx*\hyphenchar\idx*\font�
b) {\ttfamily\number\hyphenchar\font}�\idx*\ttfamily�/

\subsubsection{Dimensions de fonte}\label{espace.dimensions.fonte}\idx*[|(]{dimensions de fonte}
\begin{regle}
Pour composer du texte, chaque \idx{fonte} dispose de sept dimensions propres contenues dans des registres de dimension sp�ciaux accessibles via la primitive \idx\fontdimen. Chacun de ces registres est accessible par

\centrecode-\fontdimen<entier><fonte>-

o� \verb|<entier>| est le num�ro de la dimension (compris entre 1 et 7) et dont la signification est la suivante :

\begin{enumerate}[label=\protect\no\arabic{*}]
       \item pente par point (dimension utilis�e pour placer les accents);
       \item espace inter-mot (dimension naturelle de l'espace);
       \item �tirement inter-mot;
       \item compression inter-mot;
       \item \texttt x-height (valeur de \texttt{1ex});
       \item cadrat (valeur de \texttt{1em});
       \item espace suppl�mentaire (espace ajout� en fin des phrases).
\end{enumerate}
\end{regle}

Les plus int�ressants ici sont les \nos2, 3 et 4 qui permettent de r�gler la fa�on dont un espace se comporte lors de la composition. Pour les fontes � chasse fixe, les dimensions \nos3 et 4 sont nulles et la dimension \no2 est �gale � largeur de tous les autres caract�res.

\showcode/\leavevmode�\idx*\leavevmode�
\vbox{%�\idx*\vbox�
       \hsize=.4\hsize�\idx\hsize�
       \Souligne{Police � chasse variable}%��*\Souligne�
       \vskip5pt �\idx*\vskip�
       espace inter-mot = \the\fontdimen2\font\par�\idx*\the\idx*\fontdimen\idx*\font�
       �trirement inter-mot = \the\fontdimen3\font\par
       compression inter-mot = \the\fontdimen4\font�\idx*\the\idx*\fontdimen\idx*\font�
}\hfill�\idx*\hfill�
\vbox{%�\idx*\vbox�
       \tt�\idx*\tt�
       \hsize=.4\hsize�\idx*\hsize�
       \Souligne{Police � chasse fixe}%��*\Souligne�
       \vskip5pt �\idx*\vskip�
       espace inter-mot = \the\fontdimen2\font\par
       �trirement inter-mot = \the\fontdimen3\font\par
       compression inter-mot = \the\fontdimen4\font�\idx*\the\idx*\fontdimen\idx*\font�
}/\idx*[|)]{dimensions de fonte}

\subsubsection{Coupures de mots}
Si l'on travaille avec \LaTeX, la premi�re id�e est de r�activer les coupures de mots pour composer un texte en fonte � chasse fixe.

\showcode[\hfuzz=\maxdimen]/\def\ttwide{0.7}\def\ttindent{5}%
\hfill\vrule�\idx*\vrule�
\vbox{%
       \ttfamily�\idx*\ttfamily�
       \hyphenchar\font=`\- % change le caract�re de coupure de la fonte en cours�\idx*\hyphenchar\idx*\font�
       \setbox0\hbox{0}\parindent=\ttindent\wd0 �\idx*\setbox\idx*\hbox\idx*\parindent\idx*\wd�
       \hsize=\ttwide\hsize % compose sur 70% de la largeur�\idx*\hsize�
       Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauche
       et droite du texte ont �t� trac�es, on constate que les caract�res sont
       exactement les uns au-dessous des autres d'une ligne � l'autre. Des d�bordements
       dans la marge deviennent in�vitables m�me si les coupures des mots sont
       � nouveau rendues possibles.%
}%
\vrule\hfill\null�\idx*\vrule\idx*\hfill\idx*\null�/

Peut-on effectuer les coupures, mais ne pas ins�rer de caract�re de coupure ? La r�ponse est non, mais il est parfois possible, selon la \idx{fonte} utilis�e, de trouver un caract�re de dimension horizontale nulle et ne se traduisant par aucun dessin. On peut le chercher en construisant une macro \verb|\printallchars| moyennant une boucle �\for :

\showcode/\frboxsep=0.5pt ��*\frboxsep�
\def\printallchars{%
       \leavevmode�\idx*\leavevmode�
       \for\xx=0 to255\do{%��*\for�
               \vbox{% empiler verticalement�\idx*\vbox�
                       \offinterlineskip% en d�sactivant le ressort d'interligne�\idx*\offinterlineskip�
                       \setbox0\hbox{\frbox{\char\xx}}%�\idx*\setbox\idx*\hbox �*\frbox\idx*\char�
                       \copy0 % la boite contenant le caract�re encadr�\idx*\copy�
                       \kern1pt% saute 1pt vertical�\idx*\kern�
                       \hbox to\wd0{\hss$\scriptscriptstyle\xx$\hss}% le num�ro�\idx*\hbox\idx*\wd\idx*\hss\idx*\scriptscriptstyle�
               }\hskip0.5em plus1pt minus1pt % saute 0.5em horizontalement�\idx*\hskip�
       }%
}
\tt�\idx*\tt�
Nom de la fonte = \fontname\font\par�\idx*\fontname\idx*\font�
\printallchars/

Par chance, il semblerait que dans la \idx{fonte} � chasse fixe utilis�e dans ce livre (qui est � \texttt{GoMono} �), le caract�re \no23 de cette \idx{fonte} n'ait aucune dimension horizontale. V�rifions-le :

\showcode/\setbox0=\hbox{\tt\char23}�\idx*\setbox\idx*\hbox\idx*\tt\idx*\char�
Largeur = \the\wd0 \qquad Hauteur = \the\ht0 \qquad Profondeur = \the\dp0 �\idx*\the\idx*\wd\idx*\ht\idx*\dp�/

Il est utile de signaler que \eTeX{} offre des primitives bien pratiques pour mesurer les dimensions d'un caract�re dans une \idx{fonte} donn�e : \idx\fontcharht, \idx\fontcharwd, \idx\fontchardp et \idx\fontcharic, suivies d'une sp�cification de \idx{fonte} et d'un code de caract�res donnent des dimensions �gales � la hauteur, largeur, profondeur et correction d'italique du caract�re concern�. La dimension \verb|0pt| est renvoy�e si le caract�re n'existe pas. Le code pr�c�dent peut donc s'�crire :

\showcode/{\tt\xdef\nfont{\the\font}}�\idx*\the\idx*\font\idx*\tt\idx*\xdef�
Largeur = \the\fontcharwd\nfont23 \qquad Hauteur = \the\fontcharht\nfont23 �\idx*\fontcharwd\idx*\fontcharht\idx*\fontchardp�
\qquad Profondeur = \the\fontchardp\nfont23 /

Concernant ce caract�re \no23, il importe peu que la hauteur ne soit pas nulle puisque seule la largeur nulle rev�t une importance ici. Elle signifie que si l'on choisit ce caract�re comme caract�re de coupure avec

\centrecode-\hyphenchar\font=23 -

\noindent tout se passera comme si aucun caract�re de coupure n'�tait s�lectionn�. Cette man\oe uvre suppose bien entendu que la \idx{fonte} s'y pr�te et dispose d'un tel caract�re.
\grandsaut

Nous avons progress�, mais pas r�solu le probl�me que pose la composition sur plusieurs lignes de texte en fonte � chasse fixe : les d�bordements sont toujours bien l�, m�me s'ils sont moins importants.

\subsection{Justifier et couper}
Nous allons maintenant supprimer la premi�re contrainte vue � la page~\pageref{contraintes.tt} et nos contraintes seront donc :

\begin{enumerate}[start=2]
       \item composition justifi�e, c'est-�-dire que la distance entre le bord gauche du premier caract�re et le bord droit du dernier est toujours la m�me;
       \item coupures des mots respect�es ou carr�ment interdites.
\end{enumerate}

\noindent Respecter ces contraintes revient � � casser � l'alignement vertical des caract�res entre les lignes et en tirer parti pour supprimer --~ou au moins r�duire au minimum~-- les d�bordements dans la marge. La m�thode consiste � donner � l'espace le caract�re �tirable qu'il a dans les autres fontes, c'est-�-dire le rendre compressible et extensible dans des limites raisonnables � fixer, bien entendu. Pour cela, il faut rendre non nuls les \idx\fontdimen \nos3 et~4 de la \idx{fonte} � chasse fixe. Ici, nous allons donner une composante extensible �gale � 30\% de l'espace inter-mot et une composante compressible �gale � 20\% de cet espace. Un � environnement � sera cr�� pour l'occasion et s'�tendra entre la macro �\ttstart et \verb|\ttstop|.

Nous devons prendre nos pr�cautions pour que les modifications des param�tres de la \idx{fonte} ne restent pas globales\idx*{assignation!toujours globale}\footnote{Les assignations \texttt{\char`\\fontdimen} et\texttt{\char`\\hyphenchar} sont toujours globales, lire le \TeX book page~322. }. Pour cela, la macro \verb|\restaurefontsettings| sera charg�e de sauvegarder les param�tres de \idx{fonte} avant les modifications. Elle sera appel�e par \verb|\ttstop|, juste avant la fermeture du groupe.

\showcode/\newmacro\ttstart[5]{%��*\ttstart�*\newmacro�
       \begingroup
       \tt�\idx*\tt�
       \edef\restorefontsettings{% stocke les param�tres de fonte
               \hyphenchar\font=\the\hyphenchar\font\relax% le \hyphenchar�\idx*\the\idx*\hyphenchar\idx*\font�
               \fontdimen2\font=\the\fontdimen2\font\relax% et les param�tres d'espacement�\idx*\fontdimen�
               \fontdimen3\font=\the\fontdimen3\font\relax
               \fontdimen4\font=\the\fontdimen4\font\relax�\idx*\the\idx*\fontdimen�
       }%
       \fontdimen3\font=0.30\fontdimen2\font% composante + = 30% de la dimension naturelle�\idx*\fontdimen\idx*\font�
       \fontdimen4\font=0.20\fontdimen2\font% composante - = 20% de la dimension naturelle
       \hyphenchar\font=`\- % on autorise la coupure des mots (au cas o� on utilise latex)�\idx*\hyphenchar�
       \setbox0\hbox{0}% largeur d'un caract�re�\idx*\setbox\idx*\hbox�
       \parindent=#1\wd0 % indentation (en nombre de caract�res)�\idx*\parindent\idx*\wd�
       \ignorespaces�\idx*\ignorespaces�
}
\def\ttstop{%
       \restorefontsettings% restaure les param�tres de fonte
       \endgroup% et ferme le groupe
}
\hfill\vrule�\idx*\hfill\idx*\vrule�
\def\ttwide{0.70}%
\vbox{%
       \hsize=\ttwide\hsize % compose sur 70% de la largeur�\idx*\hsize �*\ttstart�
       \ttstart[5]
       Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauche
       et droite du texte ont �t� trac�es, on constate que les caract�res ne sont pas
       exactement les uns au-dessous des autres entre les lignes du paragraphe.
       Puisque les espaces sont redevenus �tirables, les d�bordements dans la marge
       (m�me s'ils restent possibles), sont bien plus rares et ce d'autant plus que
       le nombre d'espaces dans une ligne est grand.%
       \ttstop
}%
\vrule\hfill\null�\idx*\vrule\idx*\hfill\idx*\null�/

Le but est atteint, aucun d�bordement dans la marge n'a lieu, mais comme attendu, on perd l'alignement vertical des lettres entre les lignes. Remarquons que les valeurs 30\% et 20\% devront �tre augment�es si le nombre de caract�res par ligne diminue et r�duites dans le cas contraire.
\grandsaut

Une autre alternative aux \idx\fontdimen existe pour modifier l'espace inter-mot. Il s'agit du ressort-primitive \idx\spaceskip qui, s'il n'est pas nul, �crase les sp�cifications contenues dans \idx\fontdimen \nos2, 3 et~4. L'avantage est que sa modification tient compte des groupes et y reste locale, contrairement aux modifications de \idx\fontdimen. Ainsi, les lignes

\centrecode-\fontdimen3\font=0.30\fontdimen2\font
\fontdimen4\font=0.20\fontdimen2\font-\idx*\font

\noindent peuvent �tre remplac�es par celles-ci\idx*\font

\centrecode-\spaceskip=\fontdimen2\font �\idx*\spaceskip�
   plus0.3\fontdimen2\font
   minus0.2\fontdimen2\font-

\subsection{Justifier et aligner}
Le but ici est de supprimer la 3\ieme{} contrainte de la page~\pageref{contraintes.tt} ce qui revient � se fixer les contraintes suivantes :

\begin{enumerate}
       \item caract�res parfaitement les uns au-dessous des autres d'une ligne � l'autre;
       \item composition justifi�e, c'est-�-dire que la distance entre le bord gauche du premier caract�re et le bord droit du dernier est toujours la m�me.
\end{enumerate}

\noindent Ces deux contraintes impliquent que ces compromis doivent �tre conc�d�s:

\begin{itemize}
       \item une espace inter-lettre de dimension invariable doit �tre ins�r�e entre tous les caract�res d'une m�me ligne;
       \item les coupures peuvent se faire n'importe o�, m�me entre deux caract�res o� elles n'auraient pas eu lieu si elles avaient �t� faites par l'algorithme de coupure\footnote{Cet algorithme est d�crit � l'annexe H du \TeX book.} de \TeX.
\end{itemize}

Puisqu'une espace inter-lettre est ins�r�e entre chaque caract�re, nous allons prendre le parti de laisser � l'utilisateur la possibilit� de choisir cette espace. Pour ce faire, nous allons �crire une macro �\breaktt qui va ins�rer un \emph{faible} ressort fixe entre chaque lettre (rappelons-nous qu'un ressort est susceptible d'�tre un point de coupure). La syntaxe de cette macro sera :

\centrecode|\breaktt[<dimension inter-lettre>][<largeur de composition>]{<texte>}|

\noindent Les deux arguments optionnels permettent de sp�cifier la dimension de l'espace inter-lettre et la largeur de composition. La dimension inter-lettre sera ins�r�e \emph{apr�s} chaque caract�re, sauf le dernier de chaque ligne.

Si l'on veut que la largeur du texte soit �gale � la largeur de composition pass�e en argument, la dimension inter-lettre doit �tre choisie avec soin. Elle d�pend math�matiquement de la largeur des caract�res et de la largeur de composition. Si l'utilisateur demande une dimension inter-lettre sans pr�caution, la largeur d'une ligne sera inf�rieure � la largeur de composition. Voici le sch�ma repr�sentant la situation d'une ligne :

\begin{centrage}
\begin{tikzpicture}
\def\wdchar{0.75}\def\wdskip{.15}\def\htchar{1}
\def\extrachar{0.95}\def\numchar{10}
\def\printnextchar{%
       \let\currentabs\nextabs
       \pgfmathparse{\currentabs+\wdchar+\wdskip}\let\nextabs\pgfmathresult
       \filldraw[draw=black,fill=gray!66,line width=.5pt](\currentabs,0)rectangle(\currentabs+\wdskip,\htchar);
       \draw[line width=.5pt](\currentabs+\wdskip,0) rectangle(\nextabs,\htchar);
}
\draw[line width=1pt](0,-\htchar/2)--(0,\htchar*1.5);
\node[inner sep=0pt,outer sep=0pt,minimum size=0pt](debut)at(0,\htchar*1.4){};
\draw[line width=.5pt](0,0) rectangle ++(\wdchar,\htchar);
\let\nextabs\wdchar
\for\ii=1 to \numchar\do{\printnextchar}%
\draw[line width=1pt](\nextabs+\wdchar*\extrachar,-\htchar/2)--(\nextabs+\wdchar*\extrachar,\htchar*1.5);
\node[inner sep=0pt,outer sep=0pt,minimum size=0pt](fin)at(\nextabs+\wdchar*\extrachar,\htchar*1.4){};
\draw[stealth-stealth](debut)--(fin) node[midway,above,inner sep=0pt,outer sep=2pt]{\footnotesize Largeur de composition};
\end{tikzpicture}
\end{centrage}

Les boites englobantes des caract�res sont repr�sent�es par des rectangles vides et les espaces inter-lettres demand�es par l'utilisateur par des zones gris�es.

Pour �viter que l'utilisateur ne calcule lui-m�me la valeur du premier argument, il devient �vident qu'il doit �tre automatiquement ajust� de telle sorte que l'espace disponible � droite du dernier caract�re soit �galement r�parti dans chaque zone gris�e. Par cons�quent, la \verb|<dimension inter-lettre>| donn�e en argument \no1 ne sera pas \emph{exactement} celle ins�r�e entre chaque caract�re, mais devra �tre l�g�rement augment�e.
\grandsaut

Cherchons maintenant � formaliser le tout avec les notations suivantes :

\begin{itemize}
       \item $L$ est la largeur de composition (argument optionnel \verb|#2|);
       \item $l$ est la largeur d'un caract�re;
       \item $\Delta$ la dimension inter-lettre demand�e (argument optionnel \verb|#1|).
\end{itemize}

Compte tenu du fait que le dernier caract�re de la ligne n'est pas suivi d'une espace inter-lettre, nous allons dans un premier temps ignorer ce caract�re et soustraire $l$ � la largeur de composition $L$ pour obtenir la place disponible pour les paires \verb|<caract�re>| $+$ \verb|<dimension inter-lettre>|. Pour calculer le nombre de ces paires (de largeur $l+\Delta$), il faut prendre la partie enti�re du quotient

\[
\dfrac{L-l}{l+\Delta}
\]

En ajoutant le dernier caract�re de la ligne que nous avions ignor�, nous obtenons le nombre maximal de caract�res $n$ qu'il est possible de loger sur une ligne. Cela donne (E repr�sente l'op�rateur �partie enti�re�) :

\[n=\text{E}\left(\dfrac{L-l}{l+\Delta}\right)+1\]

Il est imm�diat que le nombre de dimensions inter-lettre est �gal � $n-1$ et donc, pour justifier le texte, il faut r�partir �galement l'espace non occup� par les caract�res entre chaque caract�re. Par cons�quent, il faut ins�rer apr�s chaque caract�re, non pas l'espace inter-lettre $\Delta$, mais

\[\Delta'=\dfrac{L-nl}{n-1}\]

Voici ce que devient le sch�ma pr�c�dent :

\begin{centrage}
\begin{tikzpicture}
\def\wdchar{0.75}\def\wdskip{.15}\def\htchar{1}
\def\extrachar{.95}\def\numchar{10}
\def\printnextchar{%
       \pgfmathparse{\nextabs+\wdchar*\extrachar/10}\let\currentabs\pgfmathresult
       \pgfmathparse{\currentabs+\wdchar+\wdskip}\let\nextabs\pgfmathresult
       \filldraw[draw=black,fill=gray!66,line width=.5pt](\currentabs,0)rectangle(\currentabs+\wdskip,\htchar);
       \draw[line width=.5pt](\currentabs+\wdskip,0) rectangle(\nextabs,\htchar);
}
\draw[line width=1pt](0,-\htchar/2)--(0,\htchar*1.5);
\node[inner sep=0pt,outer sep=0pt,minimum size=0pt](debut)at(0,\htchar*1.4){};
\draw[line width=.5pt](0,0) rectangle ++(\wdchar,\htchar);
\let\nextabs\wdchar
\for\ii=1 to \numchar\do{\printnextchar}%
\draw[line width=1pt](\nextabs,-\htchar/2)--(\nextabs,\htchar*1.5);
\node[inner sep=0pt,outer sep=0pt,minimum size=0pt](fin)at(\nextabs,\htchar*1.4){};
\draw[stealth-stealth](debut)--(fin) node[midway,above,inner sep=0pt,outer sep=2pt]{\footnotesize Largeur de composition};
\end{tikzpicture}
\end{centrage}

\noindent L'espace gris� $\Delta$ doit �tre augment� d'une petite quantit� pour que la justification se fasse. Comme l'argument optionnel \verb|#1| n'est \emph{pas} exactement l'espace qui sera ins�r� entre chaque caract�re, il doit �tre compris comme une dimension \emph{minimale} susceptible d'�tre un peu allong�e pour justifier le texte � la dimension sp�cifi�e.
\grandsaut

Entrons dans le vif du sujet et d�finissons les variables principales dont nous avons besoin :

\begin{itemize}
       \item un compteur \verb|\brktt@cnt| qui va compter, pour chaque ligne, combien de caract�res ont d�j� �t� plac�s;
       \item une macro \verb|\maxchar@num| qui contiendra $n$, le nombre de caract�res par ligne;
       \item un registre de dimension inter-lettre \verb|\brktt@interletter| pour recevoir $\Delta'$;
       \item une macro \verb|\tt@remaintext| dont le texte de remplacement contient ce qu'il reste du texte � composer;
       \item une liste de \idx{ligature}s \verb|\liglist| contenant des suites de caract�res susceptibles de former un caract�re \emph{unique}, soit par \idx{ligature} (par exemple �\verb|<<|�, �\verb|--|�, etc.) soit parce que ces caract�res sont cod�s sur plusieurs \idx{octet}s en \utf avec un moteur 8 bits\idx*{moteur!8 bits}.
\end{itemize}
\grandsaut

Le processus va se d�composer en deux. Tout d'abord, la macro �\breaktt va ouvrir un groupe semi-simple qui sera ferm� � la fin du processus et passera en mode vertical. Elle va �galement proc�der aux initialisations et aux calculs pr�alables (nombre de caract�res par ligne $n$, espace inter-lettre $\Delta'$) ainsi qu'au passage en \idx{fonte} � chasse fixe. Cette macro chapeau appellera la macro r�cursive \verb|\breaktt@i| qui imprimera, en mode vertical et dans une \idx\hbox une ligne enti�re. Ensuite, si le texte restant est vide, cela signe la fin du processus. Dans le cas contraire, la \idx\hbox doit �tre ferm�e et une nouvelle doit �tre ouverte pour accueillir la ligne suivante qui sera imprim�e par l'appel r�cursif \verb|\breaktt@i|.

Le m�canisme de fermeture/ouverture de \idx\hbox sera effectu� par la macro \verb|\restart@hbox| dont l'argument est le texte restant � composer. Apr�s avoir ferm� la \idx\hbox pr�c�dente avec \idx\egroup et avoir ouvert une nouvelle \idx\hbox avec \idx\bgroup, cette macro initialise le compteur de caract�res \verb|\brktt@cnt| � 0 et, � l'aide de �\removefirstspaces, purge son argument des �ventuels espaces qui se trouvent en premi�re position. Le r�sultat de cette op�ration est stock� dans \verb|\tt@remaintext| : ceci �vite que la prochaine ligne ne commence par une espace.

Le n\oe ud du processus sera une macro auxiliaire \verb|\print@nchar{<n>}| qui est charg�e d'afficher \verb|<n>| caract�res pris dans \verb|\tt@remaintext|. Une boucle de type �\for sera mise en \oe uvre � cet effet. Au cours de la boucle :

\begin{itemize}
       \item si \verb|\tt@remaintext| est vide, une sortie pr�matur�e de boucle doit �tre faite et la macro doit rendre la main;
       \item si \verb|\tt@remaintext| commence par un des motifs figurant dans la liste des \idx{ligature}s, le caract�re courant � afficher sera pris �gal � ce motif et dans le cas contraire au premier caract�re de \verb|\tt@remaintext|;
       \item l'espace inter-lettre ne doit pas �tre ins�r� apr�s le dernier caract�re de la ligne. Autrement dit, il ne faut ins�rer cette espace que si $\verb|\brktt@cnt|<\verb|\maxchar@num|$;
       \item si $\verb|\brktt@cnt|>\verb|\maxchar@num|$,  une sortie pr�matur�e de boucle doit �tre faite et la macro doit rendre la main.
\end{itemize}

Le bool�en \verb|\ifline@start|, inutile ici, nous servira dans d'autres versions de la macro �\breaktt.

\showcode|\catcode`\@11
\newcount\brktt@cnt�\idx*\newcount�
\newdimen\brktt@interletter�\idx*\newdimen�
\newif\ifline@start% bool�en vrai lorsqu'aucun caract�re n'est encore affich�\idx*\newif�
\newif\if@indivifound% bool�en qui sera vrai si un motif sp�cial est rencontr�\idx*\newif�

\def\insert@blankchar{%��*\ifstarred�
       \ifstarred\insert@blankchar@ii\insert@blankchar@i
}

\def\insert@blankchar@i#1{% ins�re une espace de largeur #1 caract�res complets
       \ifnum\numexpr#1\relax>0
               \kern\numexpr#1\relax\dimexpr\ttchar@width+\brktt@interletter\relax
       \fi
}

\def\insert@blankchar@ii#1{% ins�re #1-1 caract�res complets + 1 largeur de caract�re
       \ifnum\numexpr#1\relax>0
               \insert@blankchar@i{#1-1}\kern\ttchar@width�\idx*\kern�
       \fi
}

\def\restart@hbox#1{%
       \egroup% feerme la \hbox pr�c�dente
       \hbox\bgroup% ouvre la suivante�\idx*\hbox\idx*\bgroup �*\expsecond�
       \expsecond{\def\tt@remaintext}
               {\romannumeral\removefirstspaces@i{#1}}% initialiser le code � composer�\idx*\romannumeral�*\removefirstspaces�
       \let\previous@char\space% initialise le caract�re pr�c�dent�\idx*\space�
       \line@starttrue% aucun caract�re n'a encore �t� imprim�
       \brktt@cnt=0\relax% remettre le compteur � 0
}

\newmacro\breaktt[0.3em][\hsize]1{%��*\breaktt�*\newmacro�
% arg optionnel #1 et #2 = ressorts inter-lettre et dimension horizontale texte
% #3 = texte � espacer
       \begingroup% ouvrir un groupe et le fermer � la toute fin
       \par% commencer un nouveau paragraphe -> passage en mode vertical�\idx*{mode!vertical}�
       \parindent=0pt% emp�che l'indentation�\idx*\parindent�
       \tt% passer en fonte � chasse fixe�\idx*\tt�
       \setbox0 = \hbox{M}% la boite 0 contient un caract�re�\idx*\setbox\idx*\hbox�
       \edef\ttchar@width{\the\wd0 }% largeur de chaque caract�re en fonte \tt�\idx*\the\idx*\wd�
       \edef\text@width{\the\dimexpr#2\relax}% largeur de composition�\idx*\dimexpr�
       % les 2 lignes suivantes rendent le compteur �gal � E((L-l)/(l+Delta))
       \brktt@cnt=\numexpr\dimexpr#2-\wd0 \relax\relax% largeur diminu�e du 1er caract�re�\idx*\numexpr\idx*\wd�
       \divide\brktt@cnt by \numexpr\dimexpr\wd0 + #1 \relax\relax�\idx*\divide\idx*\wd�
       % le nombre de caract�re par ligne est �gal � 1 de plus :
       \edef\maxchar@num{\number\numexpr\brktt@cnt+1\relax}%
       % calcul de la dimension inter-lettre
       \brktt@interletter=\dimexpr(\text@width-\ttchar@width*\maxchar@num)/\brktt@cnt\relax
       % stocke le texte apr�s avoir enlev� les �ventuels espaces extremes :
       \expsecond{\expsecond{\def\tt@remaintext}}{\removetrailspaces{#3}}%��*\expsecond�*\removetrailspaces�
       \unless\ifx\tt@remaintext\empty% si le texte � composer n'est pas vide�\tidx*{unless}\idx*\empty�
               \hbox\bgroup% d�marrer la boite horizontale contenant la premi�re ligne�\idx*\hbox\idx*\bgroup�
               \insert@blankchar\ttindent% ins�rer une espace d'indentation
               \brktt@cnt=\ttindent\relax% tenir compte du nombre de caract�res indent�s
               \line@starttrue% il s'agit du d�but d'une ligne
               \expandafter\breaktt@i% aller � la macro r�cursive
       \fi
}

\def\breaktt@i{%
       \print@nchar\maxchar@num% afficher \maxchar@num caract�res�\defline\aaa�
       \ifx\tt@remaintext\empty% si texte restant est vide�\idx*\empty�
               \egroup% fermer la hbox�\idx*\egroup�
               \par% aller � la ligne
               \endgroup% fermer le groupe ouvert au d�but
       \else
               \unless\ifnum\brktt@cnt<\maxchar@num\relax% si la ligne est remplie�\tidx*{unless}�
                       \exparg\restart@hbox{\tt@remaintext}% ferme la hbox et en r�-ouvre une��*\exparg�
               \fi
               \expandafter\breaktt@i% enfin, continuer le processus
       \fi
}

\def\print@nchar#1{% affiche #1 caract�res pris dans \tt@remaintext
       \for\xxx= 1 to #1 \do 1{%��*\for�
               \ifx\tt@remaintext\empty% si le code restant � composer est vide�\idx*\empty�
                       \exitfor\xxx%sortir de la boucle pr�matur�ment��*\exitfor�
               \else
                       \@indivifoundfalse% sinon, a priori, les motifs de ligature ne sont pas trouv�s
                       % pour chaque \indivi@tmp dans la liste de ligatures
                       \expsecond{\doforeach\indivi@tmp\in}{\liglist}%��*\expsecond�*\doforeach�
                               {% si le code commence par la ligature courante�\idx{ligature}�
                               \exptwoargs\ifstartwith\tt@remaintext\indivi@tmp��*\exptwoargs�*\ifstartwith�
                                       {\let\previous@char\indivi@tmp% prendre le motif pour caract�re courant,
                                       \expsecond{\rightofsc\tt@remaintext}{\indivi@tmp}% l'enlever du texte restant��*\expsecond�
                                       \@indivifoundtrue% marquer qu'un motif a �t� trouv�
                                       \doforeachexit% et sortir pr�matur�ment de la boucle��*\doforeachexit�
                                       }%
                                       {}% si le code ne commence pas le motif courant -> ne rien faire
                               }%
                       \unless\if@indivifound% si aucun motif trouv�,�\tidx*{unless}�
                               \grab@first\tt@remaintext\previous@char%  lire le premier caract�re
                       \fi
                       \advance\brktt@cnt by 1 % incr�menter le compteur de caract�res�\idx*\advance�
                       \hbox to\ttchar@width{\hss\previous@char\hss}% afficher le caract�re lu�\idx*\hbox\idx*\hss�
                       \line@startfalse% nous ne sommes plus au d�but d'une ligne
                       \ifnum\brktt@cnt<\maxchar@num\relax% si la ligne n'est pas encore remplie
                               \kern\brktt@interletter% ins�rer le ressort inter-lettre�\idx*\kern�
                       \else
                               \exitfor\xxx% sinon, sortir de la boucle pr�matur�ment��*\exitfor�
                       \fi
               \fi
       }%
}
\catcode`\@12

\def\liglist{<<,>>}% liste des motifs de ligature�\idx{ligature}�
                  % ajouter �, �, etc si codage UTF8 + moteur 8 bits
\def\ttindent{3}% valeur de l'indentation'
\vrule\vbox{\breaktt[4pt][.7\hsize]{%�\idx*\vrule\idx*\vbox\idx*\hsize�*\breaktt�
Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauche
et droite du texte ont �t� trac�es, on constate que les caract�res sont
exactement les uns au-dessous des autres d'une ligne � l'autre. Plus aucun
d�bordement n'a lieu, car une espace correctement calcul�e est ins�r�e entre
chaque caract�re. Les mots, en revanche, sont toujours coup�s <<sauvagement>>.%
}%
}\vrule\smallbreak�\idx*\vrule�

\vrule\vbox{\breaktt[1pt][6cm]{%�\idx*\vrule\idx*\vbox\idx*\hsize�*\breaktt�
Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauche
et droite du texte ont �t� trac�es, on constate que les caract�res sont
exactement les uns au-dessous des autres d'une ligne � l'autre. Plus aucun
d�bordement n'a lieu, car une espace correctement calcul�e est ins�r�e entre
chaque caract�re. Les mots, en revanche, sont toujours coup�s <<sauvagement>>.%
}%
}\vrule�\idx*\vrule�|

\subsection{Aligner et ne pas couper}
Pour �viter que les mots ne soient coup�s n'importe comment, la solution radicale consiste � interdire toute coupure. L'in�vitable cons�quence est que la contrainte \no2 de la page~\pageref{contraintes.tt} (composition justifi�e) sera impossible � satisfaire.

Dans l'algorithme pr�c�dent, la macro \verb|\print@nchar| de la ligne \no\aaa{} effectuait la composition aveugle de \verb|\maxchar@num| caract�res � chaque ligne. Cette mani�re de faire est trop grossi�re et doit �tre affin�e : au fur et � mesure de l'avancement, nous allons calculer la largeur du prochain mot \verb|\next@len| par l'interm�diaire de la macro \verb|\len@tonextcut|. Il faudra ensuite tester si ce mot loge en entier dans ce qu'il reste de la ligne en cours de composition. Dans l'affirmative, nous composerons ce mot avec la macro \verb|\print@nchar| et sinon, il faudra finir la ligne en cours pour en commencer une nouvelle.

Le raffinement suppl�mentaire va �tre de tenir compte des tirets �\verb|-|� �ventuellement contenus dans les mots et rendre ces tirets comme possibles caract�res de \idx{fin de ligne}. Nous allons donc consid�rer qu'un mot est ce qui se trouve avant le plus proche des caract�res �\verb*| |� ou �\verb|-|�. Il faudra tenir compte du fait que le tiret \emph{ne disparait pas} en \idx{fin de ligne} contrairement � l'espace. Pour ce faire, une macro \verb|\extra@char| contenant 0 ou 1 nous permettra de savoir par la suite si, en plus du mot courant, il faut loger un caract�re de plus (le tiret) sur la ligne ou pas.

Nous allons baptiser �\breakttA cette variante qui compose du texte sans couper les mots. Les macros \verb|\insert@blankchar|, \verb|\restart@hbox| et \verb|\print@nchar| de la pr�c�dente variante �\breaktt seront r�utilis�es telles quelles. Elles ne sont donc pas r��crites dans le code ci-dessous. La macro \verb|\breakttA@i| ne fait plus appel � une boucle �\for, mais contient des appels r�cursifs jusqu'� ce que \verb|\tt@remaintext| ne contienne plus de texte � composer.

\showcode|\catcode`\@11
\newcount\brktt@cnt�\idx*\newcount�
\newdimen\brktt@interletter�\idx*\newdimen�
\newif\ifline@start% bool�en vrai lorsqu'aucun caract�re n'est encore affich�\idx*\newif�
\newif\if@indivifound% bool�en qui sera vrai si un motif sp�cial est rencontr�\idx*\newif�

\newmacro\breakttA[0.3em][\hsize]1{%��*\breakttA�*\newmacro�
% arg optionnel #1 et #2 = ressorts inter-lettre et dimension horizontale texte
% #3 = texte � espacer
       \begingroup% ouvrir un groupe et le fermer � la toute fin
       \par% commencer un nouveau paragraphe -> passage en mode vertical�\idx*{mode!vertical}�
       \parindent=0pt% emp�che l'indentation�\idx*\parindent�
       \tt% passer en fonte � chasse fixe�\idx*\tt�
       \setbox0 = \hbox{M}% la boite 0 contient un caract�re�\idx*\setbox\idx*\hbox�
       \edef\ttchar@width{\the\wd0 }% largeur de chaque caract�re en fonte \tt�\idx*\the\idx*\wd�
       \edef\text@width{\the\dimexpr#2\relax}% largeur de composition�\idx*\dimexpr�
       % les 2 lignes suivantes rendent le compteur �gal � E((L-l)/(l+Delta))
       \brktt@cnt=\numexpr\dimexpr#2-\wd0 \relax\relax% largeur diminu�e du 1er caract�re�\idx*\numexpr�
       \divide\brktt@cnt by \numexpr\dimexpr\wd0 + #1 \relax\relax�\idx*\divide\idx*\wd�
       % le nombre de caract�res par ligne est �gal � 1 de plus :
       \edef\maxchar@num{\number\numexpr\brktt@cnt+1\relax}%
       % calcul de la dimension inter-lettre
       \brktt@interletter=\dimexpr(\text@width-\ttchar@width*\maxchar@num)/\brktt@cnt\relax�\idx*\dimexpr�
       % stocke le texte apr�s avoir enlev� les �ventuels espaces extremes :
       \expsecond{\expsecond{\def\tt@remaintext}}{\removetrailspaces{#3}}%��*\expsecond�*\removetrailspaces�
       \unless\ifx\tt@remaintext\empty% si le texte � composer n'est pas vide�\tidx*{unless}\idx*\empty�
               \hbox\bgroup% d�marrer la boite horizontale contenant la premi�re ligne�\idx*\hbox\idx*\bgroup�
               \insert@blankchar\ttindent% ins�rer une espace d'indentation
               \brktt@cnt=\ttindent\relax% tenir compte du nombre de caract�res indent�s
               \line@starttrue% il s'agit du d�but d'une ligne
               \expandafter\breakttA@i% aller � la macro r�cursive
       \fi
}

\def\breakttA@i{%
       \edef\remaining@chars{% calculer le nombre de caract�res restant � placer sur la ligne
               \numexpr\maxchar@num-\brktt@cnt\relax}%�\idx*\numexpr�
       \len@tonextword% \next@len contient le nombre de caract�res du prochain mot
       % si le mot + l'eventuel "-" qui le suit ne peut pas loger sur la ligne en cours
       \ifnum\numexpr\next@len+\extra@char\relax>\remaining@chars\relax�\defline\aaa�
               \ifline@start% et si c'est le d�but d'une ligne
                       % avertir l'utilisateur
                       \message{Largeur de composition trop faible pour
                               \unexpanded\expandafter{\next@word}^^J}%�\idx*\message\idx*\unexpanded\verbidx[ (fin de ligne)]{^^J}�
                       % et composer tout de m�me "� la sauvage" jusqu'� la fin de la ligne
                       \exparg\print@nchar{\number\numexpr\maxchar@num-\brktt@cnt}%��*\exparg\idx*\numexpr�
               \else% si la ligne en cours n'est pas au d�but
                       \insert@blankchar*{\maxchar@num-\brktt@cnt}% remplir la ligne d'espaces
               \fi
               \exparg\restart@hbox{\tt@remaintext}% commencer une nouvelle ligne��*\exparg�
               \expandafter\breakttA@i% et poursuivre le processus
       % s'il y a assez de place pour accueillir ce qui est avant la prochaine coupure
       \else
               \print@nchar\next@len% afficher le mot�\defline\bbb�
               \ifx\tt@remaintext\empty% si texte restant est vide�\idx*\empty�
                       \insert@blankchar*{\maxchar@num-\brktt@cnt}% remplir la ligne
                       \egroup% fermer la hbox en cours�\idx*\egroup�
                       \par% aller � la ligne
                       \endgroup% fermer le groupe ouvert au d�but. Fin du processus
               \else% si le texte restant n'est pas vide
                       \ifnum\brktt@cnt<\maxchar@num\relax% si la ligne n'est pas remplie�\defline\ccc�
                                       \print@nchar{1}% afficher le caract�re qui suit le mot (" " ou "-")�\defline\ddd�
                       \else% si la ligne est remplie
                               \exparg\restart@hbox{\tt@remaintext}% ferme la hbox et en r�-ouvre une��*\exparg�
                       \fi
                       \expandafter\expandafter\expandafter\breakttA@i% enfin, continuer le processus
               \fi
       \fi
}

\def\leftofsc#1#2{% dans la macro #1, garde ce qui est � gauche de #2
       \def\leftofsc@i##1#2##2\@nil{\def#1{##1}}%
       \expandafter\leftofsc@i#1#2\@nil
}

\def\len@tonextword{% stocke dans \next@len le nombre de caract�res avant
                   % le prochain point de coupure dans \tt@remaintext
       \let\next@word\tt@remaintext% copie \tt@remaintext dans la macro temporaire \next@word
       \leftofsc\next@word{ }% ne prend que ce qui est avant le prochain espace��*\leftofsc�
       \exparg\ifin\next@word{-}% si le mot contient un tiret��*\exparg�*\ifin�
               {\leftofsc\next@word{-}% prendre ce qui est � gauche de ce tiret��*\leftofsc�
               \def\extra@char{1}% il y a un caract�re de plus � loger apr�s le mot
               }% sinon, le caract�re apr�s le mot est un espace
               {\def\extra@char{0}% qu'il ne faut pas compter
               }%
       \setbox0=\hbox{\next@word}% enfermer le mot dans une boite�\idx*\setbox\idx*\hbox�
       % et en calculer le nombre de caract�res = dim(boite)/dim(caract�re)
       \edef\next@len{\number\numexpr\dimexpr\wd0 \relax/\dimexpr\ttchar@width\relax\relax}%�\idx*\wd�
}
\catcode`\@12

\def\liglist{<<,>>}% liste des motifs de ligature (mettre �, �, etc si codage UTF8)�\idx{ligature}�
\def\ttindent{3}

\vrule\vbox{\breakttA[3pt][8cm]{%��*\breakttA�
Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauche
et droite du texte ont �t� trac�es, on constate que les caract�res sont
exactement les uns au-dessous d'une ligne � l'autre. Plus aucun d�bordement
n'a lieu, car une espace correctement calcul�e est ins�r�e entre chaque
caract�re. Dor�navant, les mots ne sont plus coup�s <<~sauvagement~>>.
}}\vrule\medbreak�\idx*\medbreak\idx*\vrule�

\leavevmode\vrule\vbox{\breakttA[1pt][5cm]{%�\idx*\leavevmode�*\breakttA�
Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauche
et droite du texte ont �t� trac�es, on constate que les caract�res sont
exactement les uns au-dessous d'une ligne � l'autre. Plus aucun d�bordement
n'a lieu, car une espace correctement calcul�e est ins�r�e entre chaque
caract�re. Dor�navant, les mots ne sont plus coup�s <<~sauvagement~>>.
}}\vrule\qquad\def\ttindent{0}%
\vrule\vbox{\breakttA[0.6pt][2cm]{mot-compos� mot-cl� passe-droit au-dessus
l�-bas remonte-pente vingt-huit Notre-Dame-de-Lourdes Mont-Blanc
Saint-Jean-de-Luz}}\vrule��*\breakttA\idx*\vrule�|

\subsection{Aligner et couper}
Entrons maintenant dans la phase la plus difficile\ldots{} Nous allons essayer de composer du texte en fonte � chasse fixe tout en alignant les caract�res les uns au-dessous des autres et en permettant que les coupures de mots se fassent.

Voici dans les grandes lignes la d�marche que nous allons suivre lorsque le prochain mot ne loge pas sur l'espace restant de la ligne en cours :

\begin{enumerate}
       \item pour le prochain mot du texte � composer (un � mot � �tant ce qui se trouve avant le plus proche espace ou tiret), nous allons trouver toutes les coupures possibles;
       \item nous allons mesurer les longueurs des syllabes ainsi obtenues et cumuler leurs longueurs de fa�on � construire la liste des nombres croissants exprimant les longueurs (en caract�res) jusqu'aux coupures possibles du mot;
       \item enfin, nous parcourons cette liste et effectuerons, si c'est possible, la coupure la plus longue possible tout en ne d�passant pas le nombre de caract�res qu'il reste � composer sur la ligne en cours. Ceci fait, il nous restera � enfermer la ligne en cours dans une \idx\hbox et en commencer une nouvelle.
\end{enumerate}

Comme plusieurs difficult�s se dressent devant nous, nous allons proc�der pas � pas.

\subsubsection{Provoquer toutes les coupures}\label{provoquer.toutes.les.coupures}
Tout d'abord, comment forcer \TeX{} � effectuer toutes les coupures possibles pour un texte donn� ? Pour l'obliger � proc�der de la sorte, nous allons composer ce texte dans une boite verticale de largeur \emph{nulle}. Bien s�r, des d�bordements auront lieu, mais nous neutraliserons leur signalement en r�glant \idx\hfuzz � \idx\maxdimen.

Avant de commencer � composer du texte en largeur nulle, certains r�glages de composition doivent �tre faits. Int�ressons-nous � la fa�on dont \TeX{} fabrique un paragraphe\idx*{paragraphe!composition} et comment nous pouvons l'influencer. Il faut savoir que \emph{plusieurs} passes peuvent �tre faites par \TeX{} pour composer un paragraphe\footnote{Pour en savoir plus, lire le \TeX book pages~112--113.}. La premi�re est tent�e si l'entier \idx\pretolerance est positif et a lieu sans faire de coupures de mots. Ceci fait, si aucune ligne du paragraphe obtenu n'a de m�diocrit�\footnote{Lire le \TeX book page 144 notamment pour comprendre comment est calcul�e la m�diocrit� d'une ligne.} sup�rieure � l'entier \idx\pretolerance, le paragraphe ainsi obtenu sera retenu. Dans le cas contraire, une seconde passe, o� les coupures de mots sont permises, est effectu�e lors de laquelle, si c'est possible, \TeX{} s'efforce de fabriquer des lignes de telle sorte qu'aucune n'ait de m�diocrit� sup�rieure � l'entier \idx\tolerance.

Comme nous cherchons � provoquer les coupures de mots, la premi�re passe ne nous int�resse pas et nous r�glerons donc \idx\pretolerance � $-1$. Par ailleurs, nous  fixerons \idx\tolerance � $10000$ de telle sorte que toutes les lignes construites � la deuxi�me passe soient acceptables\footnote{Toute valeur sup�rieure � $10000$ est comprise comme �tant �gale � $10000$.} aux yeux de \TeX.

Ensuite, il nous faut modifier localement les r�glages de composition en vue du but que nous nous sommes fix�. Comme la boite verticale de longueur nulle que nous obtiendrons a vocation � �tre coup�e en lignes avec \idx\vsplit, nous devons nous assurer qu'aucune \idx{p�nalit�} additionnelle entre les lignes n'interdit cette coupure. Voici donc les r�glages � effectuer :

\begin{itemize}
       \item l'entier \idx\hyphenpenalty, qui caract�rise la \idx{p�nalit�} d'une coupure de mots sera pris �gal � $-10000$ et donc les coupures, extr�mement favoris�es par cette p�nalit� n�gative, seront toujours effectu�es. Par ailleurs, \idx\exhyphenpenalty est la p�nalit� d'une coupure sur un caract�re explicite (le tiret). Notre algorithme ne donnera jamais � composer un mot contenant un tiret puisqu'un �mot� s'�tend jusqu'au prochain espace ou tiret. Par cons�quent, \idx\exhyphenpenalty, rendu �gal � 0, ne jouera aucun r�le.
       \item l'entier \idx\clubpenalty est ajout� � la p�nalit� de coupure de ligne pour la premi�re ligne du paragraphe. Nous prendrons $0$ comme valeur de cet entier. L'entier \idx\widowpenalty agit de m�me pour la derni�re ligne : il sera r�gl� �~0;
       \item l'entier \idx\interlinepenalty, ajout� � la \idx{p�nalit�} d'une coupure de ligne, sera pris �gal � $0$;
       \item les entiers \idx\lefthyphenmin et \idx\righthyphenmin, qui caract�risent la longueur minimale du fragment laiss� au d�but ou � la fin d'un mot coup�, seront r�gl�s � leurs valeurs par d�faut, soit \number\lefthyphenmin{} et \number\righthyphenmin{};
       \item nous r�initialiserons \idx\rightskip et \idx\leftskip � \verb|0pt| au cas o� ces dimensions ne seraient pas nulles au moment de la composition. Le ressort \idx\parfillskip sera r�initialis� � �\verb|0pt plus 1fil|� qui est sa valeur par d�faut. Nous viderons �galement \idx\everypar qui contient la liste de tokens ex�cut�e au d�but de chaque paragraphe;
       \item l'entier \idx\hyphenchar sera sauvegard� puis pris �gal � \verb|`\-| et enfin restaur� en fin de composition;
       \item l'indentation sera d�sactiv�e avec \idx\noindent tout en provoquant le passage en mode horizontal\idx*{mode!horizontal};
       \item un ressort de longueur nulle sera ins�r� avant le texte � composer, car une coupure ne peut intervenir sur un mot si ce mot commence le paragraphe. Ce ressort tiendra lieu de remplissage factice et autorisera la coupure du premier mot;
       \item la largeur de composition \idx\hsize sera rendue �gale � \verb|0pt|.
\end{itemize}

Forts de tous ces r�glages, nous allons b�tir la macro �\zerocompose :

\centrecode-\zerocompose[<code>]{<registre de boite>}{<texte>}-

\noindent o� \verb|<code>| est un code optionnel qui sera ex�cut� avant que la composition ne commence, \verb|<registre de boite>| est le num�ro du registre de la boite verticale \idx\vbox recevant le r�sultat de la composition du \verb|<texte>|.

\showcode/\newmacro\zerocompose[]2{%��*\zerocompose�*\newmacro�
% #1=code � ex�cuter avant la composition
% #2=registre de boite recevant le r�sultat
% #3= texte � composer en largeur 0pt
       \setbox#2=\vbox{%�\idx*\setbox\idx*\vbox�
               #1% code a ex�cuter (changement de fonte par exemple)
               \hfuzz=\maxdimen% annule les avertissements pour d�bordement horizontaux�\idx*\hfuzz\idx*\maxdimen\idx*{message d'avertissement}�
               \hbadness=10000 % annule les avertissements pour mauvaise boite horizontale�\idx*\hbadness\idx*{message d'avertissement}�
               \pretolerance=-1 % d�sactive la premi�re passe (celle sans coupures)�\idx*\pretolerance�
               \tolerance=10000 % passe avec coupures accept�e�\idx*\tolerance�
               \hyphenpenalty=-10000 % favorise fortement les copures de mots�\idx*\hyphenpenalty�
               \lefthyphenmin=2 \righthyphenmin=3 % longueur mini des fragments de d�but et fin�\idx*\lefthyphenmin\idx*\righthyphenmin�
               \clubpenalty=0 % pas de p�nalit� suppl�mentaire apr�s la premi�re ligne�\idx*\clubpenalty\idx{p�nalit�}�
               \interlinepenalty=0 % pas de p�nalit� inter-ligne�\idx*\interlinepenalty\idx{p�nalit�}�
               \widowpenalty=0 % pas de p�nalit� suppl�mentaire avant la derni�re ligne�\idx*\widowpenalty\idx{p�nalit�}�
               \exhyphenpenalty=0 % ne pas p�naliser une coupure explicite�\idx*\exhyphenpenalty�
               \leftskip=0pt \rightskip=0pt % d�sactive les �ventuels ressorts lat�raux�\idx*\leftskip\idx*\rightskip�
               \everypar={}% d�sactive l'�ventuel \everypar�\idx*\everypar�
               \parfillskip=0pt plus1fil % r�gle le \parfillskip par d�faut�\idx*\parfillskip�
               \hsize=0pt % largeur de composition = 0pt�\idx*\hsize�
               \edef\restorehyphenchar{\hyphenchar\font=\number\hyphenchar\font}%
               \hyphenchar\font=`\- % impose "-" comme caract�re de coupure
               \noindent % pas d'indentation + passage en mode horizontal�\idx*\noindent\idx*{mode!horizontal}�
               \hskip0pt \relax% premier noeud horizontal pour permettre la coupure de la suite�\idx*\hskip�
               #3\par% compose #3
               \restorehyphenchar% restaure le caract�re de coupure
               }%
}
\zerocompose{0}{Programmation}%�\idx*\hyphenchar\idx*\font�
\leavevmode\box0 �\idx*\leavevmode\idx*\box�
\hskip 5cm �\idx*\hskip�
\zerocompose{0}{Composer en largeur nulle}%��*\zerocompose\idx*\hyphenchar\idx*\font�
\box0 �\idx*\box�/

Malgr� les apparences, les boites \no0 affich�es dans l'exemple ci-dessus ont bel et bien une largeur \emph{nulle}. C'est \verb|\hskip 5cm| qui �vite qu'elles ne se chevauchent.

Nous allons appliquer cette m�thode � des mots seuls et utiliser \idx\vsplit pour vider peu � peu (par le haut) la boite verticale r�sultante afin d'obtenir � chaque it�ration une boite horizontale contenant une ligne de la boite initiale. Le probl�me est que la boite r�cup�r�e sera de largeur nulle puisque la \idx\vbox initiale avait cette largeur. D�s lors, il sera impossible de la mesurer pour trouver le nombre de caract�res qui la composent !

Nous allons donc faire appel � une primitive, non encore vue jusqu'alors qui va nous permettre de redonner � la boite contenant la premi�re ligne sa largeur naturelle.

\subsubsection{La primitive \texttt{\char`\\lastbox}}\idx*[|(]\lastbox

\begin{regle}
La primitive \verb|\lastbox| a un comportement tr�s particulier :

\begin{itemize}
       \item non seulement elle contient la derni�re boite compos�e dans la liste en cours, mais utiliser \verb|\lastbox| \emph{retire} cette boite de la liste dans laquelle elle �tait plac�e;
       \item si le dernier �l�ment n'est pas une boite, \verb|\lastbox| est vide;
       \item si l'on souhaite acc�der � la derni�re boite compos�e, \verb|\lastbox| s'utilise seule. Il est incorrect de la faire pr�c�der de \idx\box.
\end{itemize}

L'op�ration \verb|\lastbox| n'est pas permise dans le mode math�matique\idx*{mode!math�matique} ni dans le mode vertical\idx*{mode!vertical} \emph{principal} : elle ne peut donc pas servir � retirer une boite de la page courante en cours de composition. En revanche, elle peut tr�s bien �tre utilis�e dans le mode vertical interne\idx*{mode!vertical interne}.

La boite \verb|\lastbox| h�rite de la nature --~horizontale ou verticale~-- de la derni�re boite compos�e.

Si un registre de boite est vid� par \verb|\lastbox|, le registre ne devient pas vide, mais contient une boite vide (le test \tidx{ifvoid} est donc inadapt� pour tester si un registre est vid� par \verb|\lastbox|).
\end{regle}

La fa�on habituelle de se servir de \verb|\lastbox| est de capturer la derni�re boite pour l'assigner � un registre de boite normal que l'utilisateur peut ensuite manier � sa guise. On rencontre donc la syntaxe

\centrecode-\setbox<registre de boite>=\lastbox-

Par exemple, � l'int�rieur d'un groupe et avec l'aide de la boite brouillon \no0, \verb|\lastbox| permet d'effacer la derni�re boite compos�e :

\centrecode-{\setbox0 =\lastbox}-

On peut �galement s'en servir pour capturer la derni�re ligne d'un paragraphe compos� dans une boite verticale (dans ce cas, \verb|\lastbox| sera une boite horizontale, celle qui contient la derni�re ligne) :

\showcode/\def\dummytext{Ceci est un texte sans aucun int�r�t dont le seul but est de meubler
               la page de fa�on artificielle. }
\setbox0=\vtop{% d�finit la boite 0�\idx*\setbox\idx*\vtop�
       \hsize=8cm �\idx*\hsize�
       \dummytext\dummytext
}

a) Boite pleine : \copy0 �\idx*\copy�

b) \setbox0=\vtop{%�\idx*\setbox\idx*\vtop�
       \unvbox0 % boite pr�c�demment compos�e�\idx*\unvbox�
       \global\setbox1=\lastbox% et capture la derni�re ligne dans la boite 1�\idx*\global\idx*\setbox�
       }%
       Derni�re ligne = |\hbox{\unhbox1 }|\par% redonne � box1 sa largeur naturelle�\idx*\unhbox�
       Boite restante = \box0 /

Cet exemple illustre comment \verb|\lastbox| permet de � couper � une boite verticale par le bas. La similarit� devient �vidente entre \verb|\lastbox| qui coupe par le bas et \idx\vsplit qui coupe par le haut. En r�p�tant la man\oe uvre plusieurs fois, il deviendrait possible de vider peu � peu une boite verticale en enlevant � chaque it�ration la ligne du bas :

\showcode/\def\dummytext{Ceci est un texte sans aucun int�r�t dont le seul but est de meubler
               la page de fa�on artificielle. }
\setbox0=\vtop{% d�finit la boite 0�\idx*\setbox\idx*\vtop�
       \hsize=8cm �\idx*\hsize�
       \dummytext\dummytext
}

\setbox0=\vtop{\unvbox0 \global\setbox1=\lastbox}�\idx*\setbox\idx*\vtop\idx*\global\idx*\unvbox�
\setbox1=\hbox{\unhbox1 }�\idx*\unhbox�
1) |\box1|�\idx*\box�

\setbox0=\vtop{\unvbox0 \global\setbox1=\lastbox}
\setbox1=\hbox{\unhbox1 }�\idx*\unhbox�
2) |\box1|

\setbox0=\vtop{\unvbox0 \global\setbox1=\lastbox}�\idx*\setbox\idx*\vtop\idx*\global\idx*\unvbox�
\setbox1=\hbox{\unhbox1 }�\idx*\unhbox�
3) |\box1|�\idx*\box�/

Pourquoi \verb|\lastbox| �choue � capturer la derni�re ligne dans les deux derniers cas ? C'est que \verb|\lastbox| est plus contraignante que \idx\vsplit et la r�ponse demande de connaitre un peu la fa�on dont est construit un paragraphe\idx*{paragraphe!composition} par \TeX{} : le ressort d'interligne, qui est ins�r� entre chaque boite horizontale contenant une ligne, est assorti d'une \idx{p�nalit�} qui le pr�c�de.

Pour s'en persuader, il est possible de faire remonter des entrailles de \TeX{} vers le \idx[!log]{fichier} \verb|log| les composants �l�mentaires des boites qu'il construit. Pour ce faire, plusieurs r�glages sont � faire :

\begin{itemize}
       \item pour que les informations ne soient �crites que dans le \idx[!log]{fichier} \verb|log| (et non pas �galement sur le terminal), il faut que la primitive \idx\tracingonline soit strictement positive;
       \item l'entier \idx\showboxdepth sp�cifie le nombre de niveaux d'imbrication de boites qui doivent �tre montr�s;
       \item l'entier \idx\showboxbreadth sp�cifie le nombre d'�l�ments montr�s dans chaque niveau;
       \item la primitive \idx\showbox\label{showbox}, suivie d'un registre de boite donne l'ordre � \TeX{} d'examiner la boite contenue dans le registre et de d�livrer les informations selon les r�glages sp�cifi�s.
\end{itemize}

\errcode|\setbox0=\vbox{\hsize=2.5cm Programmer en TeX est facile}%�\idx*\setbox\idx*\vbox\idx*\hsize�
\showboxbreadth=5 \showboxdepth=3 \tracingonline=1 �\idx*\showboxbreadth\idx*\showboxdepth\idx*\tracingonline�
\showbox0 �\idx*\showbox�|{> \string\box0=\par
\string\vbox(14.77199+0.092)x71.13188\par
\string\hbox(5.27199+1.888)x71.13188, glue set - 1.0\par
.\string\hbox(0.0+0.0)x0.0\par
.\string\T1/LinuxLibertineT-TLF/m/n/8 P\par
.\string\T1/LinuxLibertineT-TLF/m/n/8 r\par
.\string\kern-0.06401\par
.\string\T1/LinuxLibertineT-TLF/m/n/8 o\par
.etc.\par
\string\penalty 300\par
\string\glue(\string\baselineskip) 2.08801\par
\string\hbox(5.52399+0.092)x71.13188, glue set 53.71591fil\par
.\string\T1/LinuxLibertineT-TLF/m/n/8 f\par
.\string\T1/LinuxLibertineT-TLF/m/n/8 a\par
.\string\discretionary\par
..\string\T1/LinuxLibertineT-TLF/m/n/8 -\par
.\string\T1/LinuxLibertineT-TLF/m/n/8 c\par
.\string\T1/LinuxLibertineT-TLF/m/n/8 i\par
.etc.}

On constate que la \idx{p�nalit�} (ici de 300) est bien ins�r�e \emph{avant} le ressort d'interligne (\idx\baselineskip). Notons par ailleurs que les �\verb|.\hbox|� repr�sentent les boites horizontales contenant les lignes (le nombre de �\verb|.|� indique le niveau d'imbrication des boites, �tant entendu qu'une absence de point indique la boite m�re). Il faut �galement remarquer, juste apr�s le �\verb|r|�, que �\verb|\kern-0.06401|� r�gle le \idx{cr�nage} (kerning) entre les caract�res �r� et �o� dans la fonte � LinuxLibertine-TLF � et montre donc que pour des raisons esth�tiques, ces caract�res sont l�g�rement rapproch�s.
\grandsaut

Pour en revenir � \verb|\lastbox|, lorsqu'elle a captur� la derni�re ligne, elle laisse en bas de la boite restante une p�nalit� et un ressort vertical. Par cons�quent, la \verb|\lastbox| suivante, ne pouvant capturer une boite, sera vide. Pour que la m�thode fonctionne, il faut supprimer \emph{dans cet ordre} le ressort avec \idx\unskip puis la \idx{p�nalit�} avec \idx\unpenalty avant d'extraire la prochaine \verb|\lastbox|. Construire une macro \verb|\reversebox| qui vide une boite verticale par le bas devient une simple routine, � condition de ne pas effectuer le test \tidx{ifvoid}, inadapt� � un registre vid� par \verb|\lastbox|, mais les tests �\ifzerodimbox ou �\ifvoidorempty que nous avons programm�s (voir page~\pageref{tester.boite.vide} et suivantes) :

\showcode/\newbox\tempbox�\idx*\newbox�
\def\reversebox#1{% affiche le contenu de la boite verticale #1
       \setbox#1=\vbox{%
               \unvbox#1% composer la boite #1�\idx*\unvbox�
               \unskip\unpenalty% retirer ce qui n'est pas capturable par \lastbox�\idx*\unskip\idx*\unpenalty�
               \global\setbox0=\lastbox% la boite 1 devient la derni�re ligne�\idx*\global\idx*\setbox�
       }%
       |\hbox{\unhbox0 }|\par% afficher la boite 1 dans sa largeur d'origine�\idx*\hbox\idx*\unhbox�
       \ifvoidorempty{#1}% si le registre #1 contient une boite vide��*\ifvoidorempty�
               \relax% ne rien faire
               {\reversebox{#1}}% sinon, rencommencer
}
\def\dummytext{Ceci est un texte sans aucun int�r�t dont le seul but est de meubler
               la page de fa�on artificielle. }
\setbox\tempbox=\vbox{% d�finit la boite 0�\idx*\setbox\idx*\vbox�
       \hsize=8cm \dummytext\dummytext�\idx*\hsize�
}

\reversebox\tempbox/

Mettons tout ceci en application. La macro �\zerocompose va nous permettre, conjointement avec \verb|\lastbox| et \idx\vsplit, de r�cup�rer une boite horizontale de largeur naturelle contenant la premi�re ligne.

\showcode/% compose "Programmation" en largeur 0 dans la boite 0 :
\zerocompose{0}{Programmation}%��*\zerocompose\idx*\font�
Boite initiale : \copy0 \par% compose la boite r�sultante�\idx*\copy�
\vfuzz=\maxdimen% annule les avertissements pour d�bordements�\idx*\vfuzz\idx*\maxdimen\idx*{message d'avertissement}�
\splittopskip=0pt % ne rajouter aucun espace au sommet de la boite restante�\idx*\splittopskip�
\setbox1 =\vsplit0 to 0pt % coupe la boite 0 � 0pt�\idx*\setbox\idx*\vsplit�
{% dans un groupe (o� la boite 0 sert de brouillon)
       \setbox0 =\vbox{% affecter � la boite brouillon�\idx*\setbox\idx*\vbox�
               \unvbox1 % la boite 1 compos�e dans sa largeur naturelle�\idx*\unvbox�
               \unskip\unpenalty% annule ce qui n'est pas une boite�\idx*\unskip\idx*\unpenalty�
               \global\setbox2 =\lastbox% affecte globalement la derni�re (et unique) ligne�\idx*\global�
                                        % � la boite 1
       }%
}% ferme le groupe
\setbox2=\hbox{\unhbox2}% rend � la boite 2 sa largeur naturelle�\idx*\hbox\idx*\unhbox�
Premi�re ligne = "\box2 "% compose la boite 2�\idx*\box�/\idx*[|)]\lastbox

\subsubsection{Mesurer toutes les coupures}
Le but est de construire une macro contenant les longueurs (en caract�res) avant les possibles coupures du mot, en tenant compte du caract�re de coupure. Par exemple, le mot � programmation � aura 3 coupures possibles auxquelles correspondent les longueurs suivantes :

\begin{centrage}
       \small
       \begin{tabular}{rc}\hline
               Caract�res avant la coupure & Longueur\\\hline
               \verb|pro-|&4\\
               \verb|program-|&8\\
               \verb|programma-|&10\\\hline
       \end{tabular}
\end{centrage}

Nous allons donc construire une macro �*\hyphlengths

\centrecode-\hyphlengths{<mot>}{\<macro>}-

\noindent qui assigne � la \verb|\<macro>| la liste de toutes les longueurs avant les coupures possibles. Par exemple, si l'on �crit �\verb|\hyphlengths{programmation}\foo|�, la macro \verb|\foo| a comme texte de remplacement �\verb|4,8,10|�.

La m�thode pour y parvenir fera intervenir

\centrecode-\vsplit<boite> to 0pt-

\noindent pour couper la boite r�sultante de la macro �\zerocompose et en obtenir la premi�re ligne dans une boite verticale. Ensuite, en composant cette boite dans une boite verticale, en capturant la derni�re boite horizontale compos�e avec \verb|\lastbox| puis en appliquant \idx\unhbox, cette ligne se retrouvera dans une boite horizontale ayant sa largeur naturelle. D�s lors qu'on peut la mesurer, il sera facile de trouver le nombre de caract�res sur chaque ligne (4, 5 et 3 pour �\verb|pro-|�, �\verb|gram-|� et �\verb|ma-|�) : la simple division de la largeur de la boite par la largeur d'un caract�re donne le quotient cherch�. Il faudra lui soustraire 1 pour �carter le caract�re de coupure. En cumulant ces nombres et en ajoutant 1 � chaque cumul pour prendre en compte le caract�re de coupure, on arrive bien � la liste �4,8,10�.

\showcode|\catcode`@11
\def\hyphlengths#1#2{%#2 = macro contenant les longueurs de coupures du mot #1��*\hyphlengths�
       \begingroup
               \zerocompose��*\zerocompose�
                       [\tt% passer en fonte � chasse fixe�\idx*\tt�
                       \setbox\z@\hbox{M}\xdef\ttwidth{\the\wd\z@}% mesurer la largeur des caract�res�\idx*\setbox\idx*\hbox\idx*\the\idx*\wd\idx*\z@\idx*\xdef�
                       ]\z@{#1}% compose en 0pt dans la boite 0�\idx*\z@�
               \let#2 = \empty% initialise la macro #2�\idx*\empty�
               \def\cumul@length{0}% le cumul des longueurs initialis� � 0
               \vfuzz=\maxdimen% annule les avertissements pour d�bordement�\idx*\vfuzz\idx*\maxdimen\idx*{message d'avertissement}�
               \splittopskip=\z@ % ne rajouter aucun espace au sommet de la boite restante�\idx*\splittopskip\idx*\z@�
               \loop�\idx*\loop�
                       \setbox1=\vsplit\z@ to \z@% couper la boite � 0pt de hauteur�\idx*\vsplit�
                       {\setbox\z@=\vbox{\unvbox1 \unskip\unpenalty\global\setbox1=\lastbox}}%�\idx*\vbox\idx*\unvbox\idx*\unskip\idx*\unpenalty\idx*\lastbox\idx*\global�
                       \setbox1=\hbox{\unhbox1 }%�\idx*\unhbox�
                       \unless\ifvoid\z@% si la boite 0 n'est pas encore vide�\tidx*{unless}\tidx*{ifvoid}\idx*\z@�
                               \edef\cumul@length{% mettre � jour \cumul@length
                                       \number\numexpr
                                               \cumul@length
                                               +% ajouter le quotient "largeur syllabe/largeur d'1 caract�re"�\idx*\wd�
                                               \wd1/\dimexpr\ttwidth\relax
                                               -1% et soustraire 1 (le caract�re "-")
                                               \relax
                               }%
                               % ajouter � #2 la virgule et le cumul actuel +1
                               \edef#2{% d�finir la macro #2 :
                                       #2% reprendre le contenu de #2
                                       \ifx#2\empty\else,\fi% ajouter "," si #2 non vide
                                       \number\numexpr\cumul@length+1\relax% et le cumul
                                       }%
               \repeat% et recommencer�\idx*\repeat�
               \expsecond{% avant de fermer le groupe��*\expsecond�
       \endgroup
       \def#2}{#2}% d�finit #2 hors du groupe
}
\catcode`\@12
a) \hyphlengths{programmation}\foo liste = "\foo"\par
b) \hyphlengths{typographie}\foo liste ="\foo"\par
c) \hyphlengths{j'entendrai}\foo liste ="\foo"\par
d) \hyphlengths{vite}\foo liste ="\foo"��*\hyphlengths�|

\subsubsection{Une solution}
Il est temps de mettre en \oe uvre toute cette th�orie. Curieusement, l'algorithme vu pr�c�demment avec �\breakttA n'a pas � subir beaucoup de changements pour autoriser les coupures de mots.

Tout ce qui est nouveau va �tre contenu dans la macro r�cursive \verb|\breakttA@i|. En premier lieu, apr�s avoir calcul� la longueur du prochain mot (qui s'�tend jusqu'� un espace ou un tiret), nous devons tester si ce mot (ainsi que l'�ventuel tiret qui le suit) peut loger sur l'espace restant de la ligne en cours. Ce n'est qu'en cas de r�ponse n�gative que nous devons entreprendre la coupure du mot. � l'aide de �\hyphlengths et en parcourant la liste de longueurs cumul�es qu'elle g�n�re, nous pouvons trouver combien mesure la plus longue coupure possible de ce mot compatible avec la place restante sur la ligne. La macro \verb|\nexthyph@len| sera cette longueur. � l'issue de ce processus, si cet entier est nul, soit aucune coupure n'�tait n�cessaire, soit aucune coupure n'a �t� trouv�e. Dans le cas o� il n'est pas nul, il sera copi� dans \verb|\next@len|.

Si une coupure doit �tre faite, le test suivant, qui s'assure que \verb|\next@len| est inf�rieur au nombre de caract�res restant � placer, est toujours vrai. Nous devons alors afficher toutes les lettres de la syllabe retenue (c'est-�-dire \verb|\next@len-1| caract�res), puis afficher un tiret, mission qu'ex�cutera la macro \verb|\print@hyphchar|. Il reste ensuite � remplir la ligne avec des caract�res blancs, fermer et ouvrir une nouvelle boite et appeler la macro \verb|\breakttA@i|.

Seules les macros \verb|\breakttA@i| et \verb|\print@hyphchar| ont �t� �crite dans cet exemple puisque toutes les autres macros d�j� vues sont strictement identiques.

\showcode|\catcode`\@11
\newcount\brktt@cnt�\idx*\newcount�
\newdimen\brktt@interletter�\idx*\newdimen�
\newif\ifline@start% bool�en vrai lorsqu'aucun caract�re n'est encore affich�\idx*\newif�
\newif\if@indivifound% bool�en qui sera vrai si un motif sp�cial est rencontr�\idx*\newif�

\let\breakttB=\breakttA��*\breakttB�

\def\breakttA@i{%
       \edef\remaining@chars{% calculer le nombre de caract�res restant � placer sur la ligne
               \numexpr\maxchar@num-\brktt@cnt\relax}%�\idx*\numexpr�
       \len@tonextword% calculer dans \next@len le nombre de caract�res avant le prochain mot
       \def\next@hyphlen{0}% initialiser la longueur de coupure possible du mot�\defline\aaa�
       % si le mot + l'eventuel "-" qui le suit ne rentre pas sur ce qui reste de la ligne
       \ifnum\numexpr\next@len+\extra@char\relax>\remaining@chars\relax
               \hyphlengths\next@word\list@hyphlengths% b�tir la liste des longueurs de coupures��*\hyphlengths�
               \unless\ifx\list@hyphlengths\empty% si une coupure est possible�\tidx*{unless}�
                       \expsecond{\doforeach\xx\in}{\list@hyphlengths}% les examiner toutes��*\expsecond�*\doforeach�
                               {% si la coupure examin�e peut loger sur la ligne
                               \unless\ifnum\xx>\remaining@chars\relax%
                                       \let\next@hyphlen\xx% la stocker
                               \fi% pour que \next@hyphlen soit maximal
                               }%
               \fi
       \fi
       \ifnum\next@hyphlen>0 % si une coupure est n�cessaire et a �t� trouv�e
               \let\next@len\next@hyphlen% mettre � jour la longueur du mot � placer
       \fi�\defline\bbb�
       % si le mot + l'eventuel "-" qui le suit ne peut pas loger sur la ligne en cours
       \ifnum\numexpr\next@len+\extra@char\relax>\remaining@chars\relax
               \ifline@start% si c'est le d�but d'une ligne
                       % avertir l'utilisateur
                       \message{Largeur de composition trop faible pour
                                \unexpanded\expandafter{\next@word}^^J}%�\idx*\message\verbidx[ (fin de ligne)]{^^J}\idx*\unexpanded�
                       % et composer tout de m�me jusqu'� la fin de la ligne
                       \exparg\print@nchar{\number\numexpr\maxchar@num-\brktt@cnt}%��*\exparg�
               \else% sinon
                       \insert@blankchar*{\maxchar@num-\brktt@cnt}% remplir la ligne
               \fi
               \exparg\restart@hbox{\tt@remaintext}% r�-ouvrir une boite��*\exparg�
               \expandafter\breakttA@i% et poursuivre le processus
       % s'il y a la place pour accueillir ce qui est avant la prochaine coupure
       \else
               \ifnum\next@hyphlen>0 % si une coupure de mot doit �tre faite�\defline\ccc�
                       \exparg\print@nchar{\number\numexpr\next@len-1}% afficher les lettres de la syllabe��*\exparg�
                       \print@hyphchar% et le caract�re de coupure
                       \insert@blankchar*{\maxchar@num-\brktt@cnt}% remplir la ligne
                       \exparg\restart@hbox{\tt@remaintext}% r�-ouvrir une boite��*\exparg�
                       \expandafter\expandafter\expandafter\breakttA@i% et continuer le processus
               \else% si pas de coupure dans le mot�\defline\ddd�
                       \print@nchar\next@len% afficher le mot
                       \ifx\tt@remaintext\tt@emptytext% si texte restant est vide
                               \insert@blankchar*{\maxchar@num-\brktt@cnt}% remplir la ligne
                               \egroup% fermer la hbox
                               \par% aller � la ligne
                               \endgroup% fermer le groupe ouvert au d�but. Fin du processus
                       \else% si le texte restant n'est pas vide
                               \ifnum\brktt@cnt<\maxchar@num\relax% si la ligne n'est pas remplie
                                               \print@nchar{1}% afficher le caract�re qui suit le mot
                               \else% si la ligne est remplie
                                       \exparg\restart@hbox{\tt@remaintext}% ferme la hbox et en r�-ouvre une��*\exparg�
                               \fi
                               \expandafter\expandafter\expandafter\breakttA@i% enfin, continuer le processus
                       \fi
               \fi
       \fi
}

\def\print@hyphchar{%
       \advance\brktt@cnt by 1 % augmenter le compteur de caract�res�\idx*\advance�
       \hbox to\ttchar@width{\hss-\hss}% afficher "-"�\idx*\hbox\idx*\hss�
       \ifnum\brktt@cnt<\maxchar@num\relax% si la ligne n'est pas encore remplie
               \kern\brktt@interletter\relax% ins�rer le ressort inter-lettre�\idx*\kern�
       \fi
}

\catcode`\@12

\def\liglist{<<,>>}% liste des motifs de ligature (mettre �, �, etc si codage UTF8)�\idx{ligature}�
\def\ttindent{3}

\vrule\vbox{\breakttB[3pt][8cm]{%�\idx*\vrule\idx*\vbox�*\breakttB�
Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauche
et droite du texte ont �t� trac�es, on constate que les caract�res sont
exactement les uns au-dessous d'une ligne � l'autre. Plus aucun d�bordement
n'a lieu, car une espace correctement calcul�e est ins�r�e entre chaque
caract�re. Dor�navant, les mots ne sont plus coup�s <<sauvagement>>.
}%
}\vrule�\idx*\vrule�

\vrule\vbox{\breakttB[1pt][5cm]{%��*\breakttB�
Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauche
et droite du texte ont �t� trac�es, on constate que les caract�res sont
exactement les uns au-dessous d'une ligne � l'autre. Plus aucun d�bordement
n'a lieu, car une espace correctement calcul�e est ins�r�e entre chaque
caract�re. Dor�navant, les mots ne sont plus coup�s <<sauvagement>>.
}%
}\vrule�\idx*\vrule�|

La macro \verb|\breakttA@i| est la m�me que vue pr�c�demment sauf que les lignes \nos\aaa--\bbb{} et \ccc--\ddd{} sont ajout�es pour permettre les coupures de mots.

Concluons ce difficile d�fi en remarquant qu'en nous aidant de celui de \TeX{}, nous avons \emph{programm�} un algorithme de coupures, mais il n'a pas toutes les fonctionnalit�s de l'original. En effet, les coupures se feront \emph{toujours} lorsqu'elles sont possibles. Il n'y a par exemple aucun moyen de d�courager des coupures, que ce soit sur des lignes adjacentes comme l'augmentation de \idx\doublehyphendemerits le permet ni sur l'avant-derni�re ligne d'un paragraphe avec \idx\finalhyphendemerits. Nous avons cependant gagn� sur un point : les coupures se feront sur des mots comprenant un trait d'union, aussi bien sur ce trait que sur le mot qui le pr�c�de ou le suit, alors que \TeX{} n'autorise une coupure que sur le trait d'union.\idx*[|)]{composition en fonte � chasse fixe}

\section{Afficher des algorithmes}
Bien que la programmation qui entre en jeu ici est \emph{lin�aire} (c'est-�-dire sans boucle), il est int�ressant de d�cortiquer la m�thode � d�ployer pour afficher des algorithmes sous forme de \idx{pseudocode} comme cela est parfois fait dans ce livre (voir par exemple ceux des pages \pageref{algo1}, \pageref{algo2} ou \pageref{algo3}).

\subsubsection{La syntaxe et les fonctionnalit�s}
Commen�ons par la syntaxe finale. La macro �\algorithm admettra un argument optionnel qui est  la liste des tokens dont le catcode sera rendu �gal � 12 pendant le pseudocode. Elle admettra aussi un argument obligatoire qui est le titre de l'algorithme (�ventuellement vide). Le \idx{pseudocode} proprement dit est contenu entre deux tokens identiques, � la mode de �\litterate :

\centrecode-\algorithm[<liste de tokens>]{<titre>}<d�limiteur><texte><d�limiteur>-

Pour que la saisie soit la plus � naturelle � possible, voici les principales fonctionnalit�s � mettre en \oe uvre:
\begin{enumerate}
       \item chaque caract�re de tabulation \verb|^^I|\verbidx[ (tabulation)]{^^I} sera traduit par une espace horizontale. La valeur de cette espace est contenue dans une macro \verb|\algoindent|;
       \item les espaces perdent leur comportement naturel et plusieurs espaces cons�cutifs seront affich�s;
       \item les retours � la ligne \verbidx[ (retour charriot)]{^^M} perdent �galement leur comportement naturel et sont reprogramm�s pour provoquer un retour � la ligne;
       \item le caract�re \cidx\~ reste actif, mais est reprogramm� pour que le \verb|<texte>| se trouvant entre deux \cidx\~ soit affich� en caract�res gras;
       \item les caract�res �\verb|:=|�, utilis�s pour une assignation, sont traduits � l'affichage par �$\leftarrow$�, provoqu� par la macro de plain-\TeX \idx\leftarrow;
       \item le caract�re �\cidx[ (mise en indice)]\_� garde son comportement normal en mode math�matique\idx*{mode!math�matique} mais est affich� tel quel sinon;
       \item le caract�re �\cidx\%� met en italique et en gris tout ce qui reste sur la ligne courante;
       \item les lignes sont num�rot�es dans la marge de gauche, mais il est possible de d�sactiver cette fonctionnalit�.
\end{enumerate}
\grandsaut

Voici ce que nous devons pouvoir �crire (o� �$\longrightarrow$� repr�sente le caract�re de tabulation):

\begingroup
\def\showcodeactivechars{\defactive\^^I{\begingroup\color{gray}${}\longrightarrow{}$\endgroup}}
\showcode/Voici un algorithme �l�mentaire :
\algorithm[\#]{Algorithme {\bf MinMax}}|
macro ~Min_Max~ (#1) % afficher la valeur max et min d'une liste de valeurs #1
       $V_{max}:=-\infty$ % $-\infty$ ou la plus petite valeur possible
       $V_{min}:=+\infty$ % $+\infty$ ou la plus grande valeur possible
       ~Pour~ chaque $x$ dans (#1)
               ~Si~ $x>V_{max}$
                       ~alors~ $V_{max}:=x$
               ~FinSi~
               ~Si~ $x<V_{min}$
                       ~alors~ $V_{min}:=x$
               ~FinSi~
       ~FinPour~
       Afficher "$V_{min}$ et $V_{max}$"
~FinMin_Max~|
Suite du texte.../
\endgroup
\grandsaut

Le probl�me �tant pos�, seuls les points \nos1 et 8 vont faire intervenir des m�thodes nouvelles.

\subsubsection{Rendre actif le caract�re de tabulation}
Pour que le caract�re de tabulation ait le comportement souhait�, la premi�re id�e serait de le rendre actif et de lui faire ins�rer horizontalement l'espace dont la mesure est contenue dans \verb|\alogoindent| :

\begingroup
\def\showcodeactivechars{\defactive\^^I{\begingroup\color{gray}${}\longrightarrow{}$\endgroup}}
\showcode/\def\algoindent{1cm}%
\begingroup
\parindent=0pt % pas d'indentation�\idx*\parindent�
\defactive\^^M{\leavevmode\par}% rend le retour charriot actif��*\defactive\verbidx*[ (retour charriot)]{^^M}�
\defactive\^^I{\hskip\algoindent\relax}% tabulation active��*\defactive\verbidx[ (tabulation)]{^^I}\idx*\hskip�
Pas d'indentation ici\ldots
       Voici une premi�re ligne
               une seconde plus indent�e
       retour � l'indentation normale
               \for\xx=1to10\do{un long texte }
       pour terminer, la derni�re ligne
\endgroup/
\endgroup

Le comportement est celui souhait� sauf lorsque le texte est trop long pour loger sur la ligne enti�re, comme celui �crit par la boucle �\for. Pour garder une coh�rence dans l'alignement vertical, il faut que l'indentation soit r�manente. La m�thode la plus imm�diate est d'incr�menter le ressort \idx\leftskip de la quantit� \verb|\algoindent| � chaque tabulation rencontr�e et remettre ce ressort � \verb|0pt| � chaque nouvelle ligne. Dans tout l'algorithme, nous assignerons un ressort infini � \idx\rightskip.

\begingroup
\def\showcodeactivechars{\defactive\^^I{\begingroup\color{gray}${}\longrightarrow{}$\endgroup}}
\showcode/\def\algoindent{1cm}%
\begingroup
\leftskip=0pt \rightskip=0pt plus1fil \relax % initialise les ressorts lat�raux�\idx*\leftskip\idx*\rightskip�
\parindent=0pt % pas d'indentation�\idx*\parindent�
\defactive\^^M{\leavevmode\par\leftskip=0pt }% rend le retour charriot actif��*\defactive\verbidx*[ (retour charriot)]{^^M}�
\defactive\^^I{\advance\leftskip by \algoindent\relax}% tabulation active��*\defactive\verbidx[ (tabulation)]{^^I}\idx*\hskip\idx*\advance\idx*\leftskip�
Pas d'indentation ici\ldots
       Voici une premi�re ligne
               une seconde plus indent�e
       retour � l'indentation normale
               \for\xx=1to10\do{un long texte }
       pour terminer, la derni�re ligne
\endgroup/
\endgroup

\subsubsection{Num�rotation des lignes}
Passons maintenant au point \no8 qui consiste � num�roter chaque ligne de l'algorithme. Une � ligne � de l'algorithme est ce qui se trouve entre deux frappes de la touche entr�e ce qui revient � consid�rer ici qu'une ligne est donc un paragraphe pour \TeX. La primitive \idx\everypar, qui se comporte comme un registre de tokens, permet de d�finir un ensemble de tokens qui seront ex�cut�s (en mode horizontal) lorsqu'un paragraphe d�bute :

\centrecode-\everypar= {<texte>}-

Nous allons mettre cette primitive � contribution pour num�roter chaque paragraphe. Pour que le num�ro soit dans la marge de gauche, nous allons le placer dans une boite en d�bordement � gauche de type \idx\llap et laisser une espace de \verb|4pt| entre ce num�ro et le d�but de la ligne. Afin que les num�ros soient correctement plac�s, nous devons tenir compte du ressort \idx\leftskip. Il faut donc laisser une espace de \verb|4pt|${}+{}$\idx\leftskip entre le num�ro et le d�but de la ligne.

\begingroup
\def\showcodeactivechars{\defactive\^^I{\begingroup\color{gray}${}\longrightarrow{}$\endgroup}}
\showcode/�\string\newcount\string\algocnt� % compteur de lignes pour l'algorithme�\idx*\newcount�
\def\algoindent{1cm}%
\begingroup
\algocnt=1 % initialise le compteur � 1
\leftskip=0pt \rightskip=0pt plus1fil\relax% initialise les ressorts � 0pt�\idx*\leftskip\idx*\rightskip�
\parindent=0pt % pas d'indentation�\idx*\parindent�
\everypar={\llap{$\scriptstyle\number\algocnt$\kern\dimexpr4pt+\leftskip\relax}}%�\idx*\llap\idx*\scriptstyle\idx*\kern\idx*\dimexpr\idx*\leftskip\idx*\everypar�

\defactive\^^M{\leavevmode\par\advance\algocnt by1 \leftskip=0pt }% retour charriot actif��*\defactive\verbidx*[ (retour charriot)]{^^M}\idx*\leavevmode\idx*\leftskip\idx*\advance�
\defactive\^^I{\advance\leftskip by \algoindent\relax}% tabulation active��*\defactive\verbidx[ (tabulation)]{^^I}\idx*\leftskip\idx*\advance�
Pas d'indentation ici\ldots
       Voici une premi�re ligne
               une seconde plus indent�e
       retour � l'indentation normale
               \for\xx=1to10\do{un long texte }
       pour terminer, la derni�re ligne
\endgroup/
\endgroup

\subsubsection{Ignorer les ind�sirables en d�but d'algorithme}
Il nous reste une astuce � pr�voir pour que la macro �\algorithm soit la plus agr�able � utiliser. Il s'agit de ce qui se trouve au d�but de l'algorithme, juste apr�s le \verb|<token>| qui d�limite le texte de l'algorithme. Pour que les choses soient plus claires, supposons que ce \verb|<token>| est �\verb-|-�. Il faudrait que l'affichage soit le m�me que l'on �crive

\begin{enumerate}
       \item \verb-\algorithm{<titre>}|d�but de l'algorithme...|-
       \item \verb-\algorithm{<titre>}|-\par
\verb-d�but de l'algorithme...|-�*\algorithm
\end{enumerate}

Il faut donc que l'on supprime tous les retours charriots (actifs) et tous les espaces (actifs) qui pourraient se trouver au tout d�but du corps de l'algorithme. Cela suppose une macro non lin�aire \verb|\sanitizealgo|, la seule de cette section. En voici l'algorithme :

\begingroup
\numalgofalse
\def\algoleftskip{.1\hsize}
\def\algorightskip{.1\hsize}
\algorithm[]{Manger tous les \texttt{\string^\string^M} et \texttt\textvisiblespace}/
macro ~lire_prochain_token~
       lire le token suivant $x$ � l'aide de \idx\futurelet
       aller � ~tester_prochain_token~
~fin~\medskip
macro ~tester_prochain_token~
       ~si~ ($x={}$\verb|espace| actif) ~ou~ ($x={}$\verbidx*[ (retour charriot)]{^^M}\verb|^^M| actif)
               manger $x$
               aller � ~lire_prochain_token~
       ~finsi~
~fin~/
\endgroup

Nous appellerons cette macro \emph{en dernier} puis, une fois son travail effectu�, nous laisserons \TeX{} composer le texte constituant l'algorithme. On ne pourra reprendre la main que lorsqu'il ex�cutera le \verb|<d�limiteur>| final rendu actif qui fermera le groupe ouvert tout au d�but, tracera la ligne horizontale de fin d'algorithme et sautera une petite espace verticale � l'aide de \idx\smallbreak.

\subsubsection{Commentaires gris�s avec le package \texttt{color}}
Enfin, pour que les commentaires soient en italique et en gris, nous allons rendre le caract�re �\cidx\%� actif de fa�on � ce qu'il s�lectionne la \idx{fonte} italique (avec \idx\it) et colore le texte � venir en gris (avec \verb|\color{gray}|). Cette derni�re action suppose que la couleur �\verb|gray|� a �t� d�finie et que le \idx[!color]{package} �\verb|color|� a pr�alablement �t� charg� moyennant :

\begin{itemize}
       \item \idx\usepackage\verb|{color}| pour le \idx[!\LaTeX]{format} \LaTeX{};
       \item \idx\input\verb| color| pour le \idx[!plain-\TeX]{format} plain-\TeX{};
       \item \idx\setupcolor\verb|[state=start]| pour le \idx[!Con\TeX t]{format} Con\TeX t.
\end{itemize}

Pour que la typographie normale (caract�res non italiques et couleur noire) soit � nouveau en vigueur � la ligne suivante, nous chargerons le caract�re actif \verbidx*[ (retour charriot)]{^^M}\verb|^^M| d'effectuer les actions �\idx\rm� pour un retour en \idx{fonte} droite et �\verb|\color{black}|� pour restaurer la couleur noire.

\subsubsection{Le code complet}
Voici le code complet comment� qui reprend des m�thodes d�j� vues plusieurs fois (programmation de caract�res actifs notamment) :

\begingroup
\defactive\W{\begingroup\color{gray}${}\longrightarrow{}$\endgroup}
\showcode[\defactive\W{\advance\leftskip\algoindent\relax}]/\newif\ifnumalgo�\idx*\newif�
\newcount\algocnt�\idx*\newcount�
\numalgotrue

\def\algoindent{2em}
\def\algorule{.4pt}% �paisseur des r�glures de d�but et de fin

\def\algohrulefill{% remplit avec une ligne horizontale
       \leavevmode�\idx*\leavevmode�
       \leaders\hrule height\algorule\hfill�\idx*\leaders\idx*\hrule\idx*\hfill�
       \kern0pt % rajoute un noeud au cas o� la commande est en fin de ligne�\idx*\kern�
}

\newmacro\algorithm[\\,\#,\{,\}]2{%��*\algorithm�*\newmacro�
       \medbreak�\idx*\medbreak�
       \begingroup% ouvre un groupe (sera ferm� � la fin de l'algorithme)�\defline\aaa�
               \algocnt=1 % initialise le compteur de lignes
               \leftskip=0pt \rightskip=0pt plus1fil\relax% initialise les ressorts lat�raux�\idx*\leftskip\idx*\rightskip�
               \parindent=0pt % pas d'indentation�\idx*\parindent�
               %%%%%%%%%%%% affichage du titre %%%%%%%
               \algohrulefill% remplir avec une ligne horizontale
               \ifempty{#2}% si #2 est vide��*\ifempty�
                       {}% ne rien ins�rer
                       {% sinon
                       \lower.5ex\hbox{ #2 }% ins�rer le titre abaiss� de 0.5ex�\idx*\lower\idx*\hbox�
                       \algohrulefill% ins�rer une ligne horizontale
                       }%
               \par% aller � la ligne
               \nointerlineskip% ne pas ins�rer le ressort d'interligne�\idx*\nointerlineskip�
               \kern7pt % et sauter 7pt verticalement�\idx*\kern�
               \nobreak% emp�cher une coupure de page�\idx*\nobreak�
               %%%%%%%%%%%%%% fin du titre %%%%%%%%%%
               %
               %%%%%%%%%%%%%% rend les caract�res actifs %%%%%%%%%%%%%%
               \def~##1~{\begingroup\bf##1\endgroup}%�\idx*\bf�
               \defactive:{% rend ":" actif��*\defactive�
                       \futurelet\nxttok\algoassign% \nxttok = token suivant�\idx*\futurelet�
               }%
               \def\algoassign{% suite du code de ":"
                       \ifx=\nxttok% si ":" est suivi de "="
                               \ifmmode% si mode math�\tidx*{ifmmode}\idx*{mode!math�matique}�
                                       \leftarrow% afficher "\leftarrow"�\idx*\leftarrow�
                               \else% si mode texte
                                       ${}\leftarrow{}$% passer en mode math pour "\leftarrow"�\idx*{mode!math�matique}�
                               \fi
                               \expandafter\gobone% manger le signe "="
                       \else% si ":" n'est pas suivi de "="'
                               \string:% afficher ":"�\idx*\string�
                       \fi
               }%
               \ifnumalgo% si la num�rotation est demand�e,
                       \everypar={% d�finir le \everypar
                               \llap{$\scriptstyle\number\algocnt$\kern\dimexpr4pt+\leftskip\relax}%
                       }%�\idx*\llap\idx*\scriptstyle\idx*\kern\idx*\dimexpr\idx*\leftskip\idx*\everypar�
               \fi
               \doforeach\currentchar\in{#1}{\catcode\expandafter`\currentchar=12 }%��*\doforeach�
               \def\algocr{% d�finit ce que fait ^^M
                       \color{black}% repasse en couleur noire�\idx*\color�
                       \rm% fonte droite�\idx*\rm�
                       \leavevmode\par% termine le paragraphe
                       \advance\algocnt by1 % incr�mente le compteur de lignes�\idx*\advance�
                       \leftskip=0pt % initialise le ressort gauche�\idx*\leftskip�
               }
               \letactive\^^M=\algocr%��*\letactive\verbidx*[ (retour charriot)]{^^M}�
               \defactive\^^I{\advance\leftskip by \algoindent\relax}%��*\defactive\verbidx[ (tabulation)]{^^I}\idx*\advance\idx*\leftskip�
               \defactive\ {\hskip1.25\fontdimen2\font\relax}% espace = 25% de + que
                                                             % la largeur naturelle�\idx*\hskip\idx*\fontdimen\idx*\font�
               \defactive\%{\it\color{gray}\char`\%}% passe en italique et gris puis affiche "%"�\idx*\it\idx*\char\idx*\color\cidx*\%�
               \defactive_{\ifmmode_\else\string_\fi}%�\tidx*{ifmmode}\idx*\string�
               \defactive#3{% rend le token #3 actif (il sera rencontr� � la fin de l'algorithme)��*\defactive�
                       \everypar{}% neutralise le \everypar�\idx*\everypar�
                       \par% aller � la ligne
                       \nointerlineskip% ne pas ins�rer le ressort d'interligne�\idx*\nointerlineskip�
                       \kern7pt % et sauter 7pt verticalement�\idx*\kern�
                       \nobreak% emp�cher une coupure de page�\idx*\nobreak�
                       \algohrulefill% tracer la ligne de fin
       \endgroup% ferme le groupe ouvert au d�but de l'algorithme�\defline\bbb�
       \smallbreak% saute un petit espace vertical�\idx*\smallbreak�
               }%
       %%%%%%%%%%%%%%%%% fin des caract�res actifs %%%%%%%%%%%%%%%%
       \sanitizealgo% va manger les espaces et les ^^M au d�but de l'algo
}

\def\sanitizealgo{\futurelet\nxttok\checkfirsttok}% r�cup�re le prochain token�\idx*\futurelet�

\def\checkfirsttok{% teste le prochaun token
       \def\nextaction{% a priori, on consid�re que la suite est " " ou "^^M" donc
               \afterassignment\sanitizealgo% aller � \sanitizealgo�\idx*\afterassignment�
               \let\nexttok= % apr�s avoir mang� ce "^^M" ou cet espace
       }%
       \unless\ifx\nxttok\algocr% si le prochain token n'est pas un ^^M�\tidx*{unless}�
               \unless\ifx\space\nxttok% et si le prochain token n'est pas un espace�\idx*\space�
                       \let\nextaction\relax% ne rien faire ensuite
               \fi
       \fi
       \nextaction% faire l'action d�cid�e ci-dessus
}

Voici un algorithme �l�mentaire
\algorithm[\#]{Algorithme {\bf MinMax}}|
macro ~Min_Max~ (#1) % afficher la valeur max et min d'une liste de valeurs #1
W$V_{max}:=-\infty$ % $-\infty$ ou la plus petite valeur possible
W$V_{min}:=+\infty$ % $+\infty$ ou la plus grande valeur possible
W~Pour~ chaque $x$ dans (#1)
WW~Si~ $x>V_{max}$
WWW~alors~ $V_{max}:=x$
WW~FinSi~
WW~Si~ $x<V_{min}$
WWW~alors~ $V_{min}:=x$
WW~FinSi~
W~FinPour~
WAfficher "$V_{min}$ et $V_{max}$"
~FinMin_Max~|
Suite du texte.../% TODO : dans le fichier des codes, remplacer "W" par "TAB"
\endgroup

L'algorithme obtenu peut franchir des sauts de page et donc s'�tendre sur plusieurs pages. Ce comportement peut �tre facilement interdit en englobant la totalit� de l'algorithme dans une boite verticale de type \idx\vbox ou \idx\vtop. On peut par exemple remplacer le \idx\begingroup de la ligne \no\aaa{} par \idx\vbox\idx\bgroup qui marquera le d�but de la boite et en profiter, si on le souhaite pour ajuster la largeur \idx\hsize. Il faudra �galement remplacer le \idx\endgroup de la ligne \no\bbb{} par \idx\egroup qui fermera la boite.

\chapter*{Conclusion}
\addcontentsline{toc}{part}{Conclusion}

Nous voil�, cher lecteur, arriv�s � la fin de notre p�riple. Nous en savons beaucoup plus qu'au d�but, mais il reste tant � d�couvrir, tant � exp�rimenter\ldots{} Le maitre mot est d'essayer de coder par soi m�me; c'est un poncif tant c'est r�p�t�, mais c'est en programmant qu'on devient programmeur. Pas en lisant un livre sur le sujet.

Si les notions abord�es dans ce livre ont balay� le plus large champ possible pour permettre un d�but d'autonomie, elles ne sont pas exhaustives. Par exemple, nous n'avons jamais parl� de la routine de sortie qui occupe � elle seule un chapitre entier (le \no23) du \TeX book. De la m�me fa�on, pas un mot n'a �t� dit sur les insertions, m�canisme souple et puissant utilis� dans les notes de bas de page ou les notes marginales. Nous avons � peine effleur� les alignements et les tableaux de \TeX{} alors que ce sujet est d'une grande richesse. Il y reste donc des pans entiers � d�couvrir\ldots
\grandsaut

Bonne chance donc et avant tout, cher lecteur, prenez du plaisir avec \TeX{} !
%|                                                                            |
%|                                Fin partie 5                                |
%|____________________________________________________________________________|

% ____________________________________________________________________________
%|                                                                            |
%|                                   Annexes                                  |
%|                                                                            |
\immediate\closeout\reglewrite
\part{Annexes}
\chapter{D�bogage}\idx*[|(]{d�bogage}
Le d�bogage est un art difficile qui consiste � trouver pour quelle(s) raison(s) un programme ne fonctionne pas comme on s'y attend. Certes, la relecture du code accompagn�e de la simulation mentale de son fonctionnement permet parfois de trouver o� se trouve l'erreur. Bien souvent h�las, cet exercice est insuffisant pour d�busquer l'endroit o� se cache le �\emph{bug}� . Il faut alors s'en remettre � des instructions de d�bogage.

\section{D�livrer les informations stock�es}
Nous allons d'abord examiner les instructions qui font remonter des entrailles de \TeX{} ce qui est contenu dans les diff�rentes structures de donn�es permettant de stocker de l'information (primitives, macros ou registres). Nous avons d�j� vu que \idx\meaning\verb|<token>| se d�veloppait en tokens de catcode 12\idx*{catcode!12 (autre)} qui, selon ce qu'est le \verb|<token>| :

\begin{itemize}
       \item est le nom de la primitive si ce \verb|<token>| est une primitive ;
       \item est le \idx{texte de param�tre} et le \idx{texte de remplacement} dans le cas d'une macro;
       \item est le \verb|<token>| lui-m�me accompagn� de sa nature si c'est un caract�re.
\end{itemize}

\showcode/a) \meaning a\par
b) \meaning {\par
c) \meaning _\par
d) \meaning\def\par % une primitive
e) \meaning\baselineskip\par% une primitive�\idx*\baselineskip�
f) \long\def\foo#1#2.#3{#1 puis #2 et #3 !}\meaning\foo�\idx*\long�/

La primitive \idx\show a un comportement identique sauf que ces informations sont �crites dans le \idx[!log]{fichier} \verb|log| et sur le terminal. Cela pr�sente l'avantage de ne pas surcharger l'affichage comme peut le faire \idx\meaning, � condition d'aller lire le \idx[!log]{fichier} \verb|log| apr�s la compilation.

Pour connaitre l'argument d'une macro, \idx\show manque de souplesse puisqu'il faut d�finir une macro auxiliaire dont le texte de remplacement est cet argument et enfin, donner cette macro � \idx\show :

\errcode/\def\foo#1#2{%
       \def\argA{#1}\show\argA% d�bogage�\idx*\show�
       Bonjour #1 et #2}
\foo{{\bf X}}{Y}�\idx*\bf�/{\ttfamily> \string\argA=macro:\par
->\string{\string\bf\space X\string}.}

Le moteur \eTeX{}\idx*{moteur!etex} fournit la primitive\idx*\showtokens

\centrecode-\showtokens{<ensemble de tokens>}-

\noindent et �crit sur le terminal et dans le \idx[!log]{fichier} \verb|log| cet \verb|<ensemble de tokens>|. De plus, cette primitive devant �tre suivie d'une accolade ouvrante, elle ob�it � la r�gle que partagent les primitives poss�dant cette propri�t� : elle d�veloppe tout jusqu'� trouver cette accolade ouvrante.

\errcode/\def\foo#1#2{%
       \showtokens{#1}% d�bogage�\idx*\showtokens�
       Bonjour #1 et #2}
\foo{{\bf X}}{Y}/{\ttfamily>\string{\string\bf\space X\string}.}
\grandsaut

La primitive \idx\show reste pourtant inop�rante pour afficher quel est le contenu d'un registre, qu'il soit primitive (comme \idx\baselineskip) ou d�fini par l'utilisateur (comme un registre d'entier par exemple).

\errcode/\newtoks\footoks
\footoks={foo bar}
\show\footoks�\idx*\show�/{\ttfamily> \string\footoks=\string\toks62.}

Pour extraire les valeurs contenues dans des registres de dimension, de ressort, d'entier ou de tokens, la primitive \idx\showthe doit �tre utilis�e :

\errcode/\showthe\baselineskip% registre-primitive�\idx*\showthe\idx*\baselineskip�
\newtoks\footoks \footoks={foo bar} \showthe\footoks�\idx*\newtoks�
\newcount\foocount \foocount=987 \showthe\foocount�\idx*\newcount�
\newdimen\foodimen \foodimen=3.14pt \showthe\foodimen�\idx*\newdimen�
\newskip\fooskip \fooskip=10 pt plus 1pt minus 1fil \showthe\fooskip�\idx*\newskip�
\newbox\foobox \foobox\hbox{foo} \showthe\foobox�\idx*\newbox\idx*\showthe�/{> 12.0pt.\par
> foo bar.\par
> 987.\par
> 3.14pt.\par
> 10.0pt plus 1.0pt minus 1.0fil.\par
> 101.}

Le dernier registre, celui de boite, �chappe � \idx\showthe. Cela est d� au fait que \idx\newbox d�finit \verb|\foobox| � l'aide de \idx\chardef puisqu'il n'existe pas de primitive \verb|\boxdef|. Nous avons vu que pour demander � \TeX{} de donner la composition d'une boite, il faut passer par la primitive \verb|\showbox| (voir page~\pageref{showbox}).
\grandsaut

Correctement placer les instructions de d�bogage telles que \idx\show, \idx\showthe et \idx\showtokens afin de se donner le maximum de chances de trouver le dysfonctionnement n'est pas trivial et demande souvent plusieurs essais-erreurs. Bien souvent, l'enqu�te consiste � suivre l'�volution du \idx{texte de remplacement} d'une macro (avec \idx\show{}), comprendre comment se transmet un argument entre plusieurs macros (avec \idx\showtokens{}) ou �\emph{tracer}� la valeur d'un registre (avec \idx\showthe{}).

\section{D�livrer des informations sur l'ex�cution}
\TeX{} fournit �galement des primitives qui permettent de contr�ler quelles informations seront affich�es dans le \idx[!log]{fichier} \verb|log| lors de l'ex�cution du code. Une fois la compilation faite, l'examen de ces informations retrace, selon la pr�cision demand�e, ce que \TeX{} a fait.

La primitive \idx\tracingmacros se comporte comme un registre d'entier. Lorsqu'elle re�oit un entier strictement positif, \TeX{} donnera dans le \idx[!log]{fichier} \verb|log| des informations sur chaque macro d�velopp�e : son nom, son texte de param�tre, son texte de remplacement et si elle admet des arguments, la valeur des arguments lus au moment du d�veloppement.

\errcode-\def\foo#1,#2\endfoo{Bonjour #1 et #2}
\tracingmacros=1
\foo moi,toi\endfoo
\tracingmacros=0-{\ttfamily\string\foo\space\#1,\#2\string\endfoo{} ->Bonjour \#1 et \#2\par
\#1<-moi\par
\#2<-toi}

Une autre aide au diagnostic est fournie par la primitive \idx\tracingcommands, qui est �galement de type entier. En assignant un nombre strictement positif � cette primitive, \TeX{} �crira dans le \idx[!log]{fichier} \verb|log| toutes les commandes qu'il ex�cute. Si l'entier vaut 2 ou plus, les tests et leurs issues seront �galement montr�s.

\errcode-\tracingcommands=2
Foo \hbox{et \ifnum2>1 bar\else toi\fi}\par
Suite
\tracingcommands=0-{\ttfamily\{vertical mode: the letter F\}\par
\{horizontal mode: the letter F\}\par
\{blank space  \}\par
\{\string\hbox\}\par
\{restricted horizontal mode: the letter e\}\par
\{blank space  \}\par
\{\string\ifnum\}\par
\{true\}\par
\{the letter b\}\par
\{\string\else\}\par
\{end-group character \}\}\par
\{horizontal mode: \string\par\}\par
\{vertical mode: the letter S\}\par
\{horizontal mode: the letter S\}\par
\{blank space  \}\par
\{\string\tracingcommands\}\par}

Les espaces parasites g�n�r�s par des fins de ligne non comment�es peuvent facilement �tre d�busqu�s en cherchant �\texttt{blank space}� dans le \idx[!log]{fichier} \verb|log|.
\grandsaut

Pour d�boguer des programmes, la macro \idx\tracingrestores peut �galement s'av�rer utile. Elle est �galement de type entier et indique dans le \idx[!log]{fichier} \verb|log| ce que \TeX{} garde en m�moire lorsque des assignations sont locales. Ces instructions plac�es dans la \emph{\idx{pile de sauvegarde}} sont d�pil�es � la sortie du groupe pour restaurer la variable � son �tat ant�rieur. Si une assignation est globale, rien n'est plac� dans la pile et la derni�re valeur globale assign�e sera celle en vigueur � la sortie du groupe

Prenons un exemple inspir� de celui du \TeX book. Afin d'�viter de d�finir un compteur, utilisons celui qui porte le \no255 et d�finissons la macro \verb|\i| qui incr�mente ce compteur.

\errcode/\def\i{\advance\count255 1 }
\tracingrestores=1
\count255=2 {\i\i\i}�\defline\aaa�
\tracingrestores=0/{\ttfamily\{restoring \string\count255=2\}}

L'instruction �\verb|{restoring \count255=2}|� refl�te ce qui ex�cut� � la fin du groupe. L'instruction �\verb|\count255=2|� a �t� plac�e sur la \idx{pile de sauvegarde} lorsque le premier \verb|\i| a �t� ex�cut�.

Lorsqu'une assignation est globale, la derni�re valeur globale assign�e devient celle qui sera en vigueur � la sortie du groupe. D�s lors, les pr�c�dentes instructions de sauvegarde plac�es sur la \idx{pile de sauvegarde} deviennent inutiles, mais elles y restent et seront ignor�es � la sortie du groupe. Mettons ceci en �vidence avec la macro \verb|\gi| qui incr�mente globalement le compteur \no255 :

\errcode/\def\i{\advance\count255 1 } \def\gi{\global\i}�\idx*\global�
\tracingrestores=1
\count255=2 {\i\i\gi\i\gi\i}
\tracingrestores=0/{\{restoring \string\count255=7\}\par
\{retaining \string\count255=7\}\par
\{retaining \string\count255=7\}}

Les empilements sur la \idx{pile de sauvegarde} ont lieu :

\begin{enumerate}
       \item lorsque le premier \verb|\i| est ex�cut�;
       \item au troisi�me \verb|\i|, qui modifie localement une valeur rendue globale par le \verb|\gi| pr�c�dent;
       \item au dernier \verb|\i| qui � nouveau, modifie localement une valeur globale.
\end{enumerate}

Au d�pilement qui se fait dans l'\emph{ordre inverse} de l'empilement, seule la derni�re valeur de sauvegarde 7 est prise en compte. Les deux derniers ordres de sauvegarde sont ignor�s et la valeur 7 est retenue. Cela se traduit dans le \idx[!log]{fichier} \verb|log| par lignes contenant le mot �\texttt{retaining}� et non pas �\texttt{restoring}�.

Il faut donc �tre conscient qu'effectuer localement des assignations locales \emph{et} globales peut charger la \idx{pile de sauvegarde} inutilement. Dans les faits, une instruction de sauvegarde est empil�e chaque fois qu'une assignation locale suit une assignation globale. La \idx{pile de sauvegarde} n'est �videmment pas infinie et un d�passement de sa capacit� se traduit par une erreur � la compilation de type �\texttt{save size capacity exceeded}.�\idx*[|)]{d�bogage}

\chapter{Programmer l'addition d�cimale}\label{decadd}�*\decadd[|(]%
Comme nous l'avons vu et expliqu� � la page~\pageref{arrondis.sur.dimensions}, l'addition sur les dimensions pose des probl�mes d'arrondis conduisant � des r�sultats faux. Ces erreurs, insignifiantes pour une dimension, sont inacceptables lorsque ces nombres sont consid�r�s comme entit�s math�matiques. Il est donc utile de programmer une macro purement d�veloppable �\decadd\verb|{<d�cimal 1>}{<d�cimal 2>}| qui ne pr�sente pas les d�fauts de l'addition sur les dimensions.

Ayant � notre disposition l'addition des entiers relatifs, programmer une simple addition de deux nombres d�cimaux relatifs semble trivial. Pourtant\ldots{}

\section{Proc�dure math�matique}
Appelons $a$ et $b$ les deux nombres � additionner. Si les deux nombres sont entiers, le probl�me est r�solu : il suffit de les additionner avec \idx\numexpr qui ne proc�de � aucun arrondi.

Si l'un d'entre eux est entier, il faut d'abord le transformer en nombre d�cimal en ajoutant � \verb|.0| �. Ceci fait, les deux nombres $a$ et $b$ sont de la forme �$x.y$� o� $x$ est un entier relatif et $y$ un entier naturel. Ensuite, nous allons transmettre le signe de $x$ � $y$ de telle sorte que l'entier repr�sentant la partie enti�re et celui repr�sentant la partie d�cimale aient le m�me signe. Par exemple, si $a=-3.14$, alors $x_a=-3$ et $y_a=-14$.

L'addition se fait donc entre deux nombres de la forme $x_a.y_a$ et $x_b.y_b$ o� $x_a$, $x_b$, $y_a$ et $y_b$ sont des entiers \emph{relatifs}. Nous allons transformer les parties d�cimales pour qu'elles aient le m�me nombre de chiffres en rajoutant � l'une d'entre-elles, si c'est n�cessaire, des 0 inutiles � sa droite. Une fois ceci effectu�, on d�finit $10^n$ comme la puissance de 10 imm�diatement sup�rieure � $|y_a|$ ou $|y_b|$ que l'on nomme �seuil de retenue�.

La m�thode consiste ensuite � ajouter ind�pendamment les parties enti�res et les parties d�cimales. Pour que les choses soient plus claires, les parties enti�res et d�cimales sont s�par�es par une ligne verticale :

\begin{centrage}\small
       \begin{tabular}{rr|l}
               &$x_a$&$y_a$\\
       +       &$x_b$&$y_b$\\\hline
               &$x$  &$y$
       \end{tabular}
\end{centrage}

On examine ensuite les nombres relatifs $x$ et $y$ obtenus. Si l'on note $\sigma_x$ le signe de $x$ (ou celui de $y$ si $x$ est nul) et $\sigma_y$ celui de $y$, alors, le cas est favorable se produit lorsque $|y|<10^n$ (pas de retenue) et $\sigma_x=\sigma_y$. Le r�sultat est alors le nombre d�cimal

\[
\begin{cases}
x.|y|&\text{ si } x\neq0\\
\sigma_y0.|y|&\text{ si } x=0
\end{cases}
\]

Deux cas d�favorables peuvent se pr�senter :

\begin{enumerate}
       \item $x$ et $y$ sont de signes contraires. Ces additions en sont des illustrations :
       \begin{centrage}\small
               \begin{tabular}{rr|r}
                       &$7$&$20$\\
               +       &$-4$&$-45$\\\hline
                       &$3$  &$-25$
               \end{tabular}\hskip0.1\linewidth
               \begin{tabular}{rr|r}
                       &$2$&$70$\\
               +       &$-4$&$-15$\\\hline
                       &$-2$  &$55$
               \end{tabular}
       \end{centrage}

       Dans ce cas, afin que $x$ et $y$ satisfassent les conditions du cas favorable, les modifications suivantes doivent y �tre apport�es :

       \[\begin{cases}
       x\longleftarrow x-\left(\sigma_x1\right)\\
       y\longleftarrow y-\left(\sigma_y10^n\right)
       \end{cases}\]

       Les additions pr�c�dentes deviennent :
       \begin{centrage}\small
               \begin{tabular}{rr|r}
                       &$7$&$20$\\
               +       &$-4$&$-45$\\\hline
                       &$3$  &$-25$\\
                       &$3-(1)$&$-25-(-100)$\\
               =       &$2$&$75$
               \end{tabular}\hskip0.1\linewidth
               \begin{tabular}{rr|r}
                       &$2$&$70$\\
               +       &$-4$&$-15$\\\hline
                       &$-2$  &$55$\\
                       &$-2-(-1)$&$55-(100)$\\
               =       &$-1$&$-45$
               \end{tabular}
       \end{centrage}

       \item $x$ et $y$ sont de m�me signe \emph{et} $|y|\geqslant10^n$, comme dans ces additions :
       \begin{centrage}\small
               \begin{tabular}{rr|r}
                       &$7$&$20$\\
               +       &$4$&$95$\\\hline
                       &$11$  &$115$
               \end{tabular}\hskip0.1\linewidth
               \begin{tabular}{rr|r}
                       &$-2$&$-70$\\
               +       &$-4$&$-65$\\\hline
                       &$-6$  &$-135$
               \end{tabular}
       \end{centrage}
       Pour que $x$ et $y$ v�rifient les conditions du cas favorable, leurs valeurs doivent �tre modifi�es selon la r�gle suivante :

       \[\begin{cases}
       x\longleftarrow x+\left(\sigma_x1\right)\\
       y\longleftarrow y-\left(\sigma_y10^n\right)
       \end{cases}\]

       Les deux additions pr�c�dentes deviennent alors :
       \begin{centrage}\small
               \begin{tabular}{rr|r}
                       &$7$&$20$\\
               +       &$4$&$95$\\\hline
                       &$11$  &$115$\\
                       &$11+(1)$&$115-(100)$\\
               =       &$12$&$15$
               \end{tabular}\hskip0.1\linewidth
               \begin{tabular}{rr|r}
                       &$-2$&$-70$\\
               +       &$-4$&$-65$\\\hline
                       &$-6$  &$-135$\\
                       &$-6+(-1)$&$-135-(-100)$\\
               =       &$-7$&$-35$\\
               \end{tabular}
       \end{centrage}
\end{enumerate}

\section{Mise en \oe uvre}
\subsection{Rendre les nombres d�cimaux}
Dans un premier temps, la macro �\decadd doit s'assurer que les parties d�cimales sont bien pr�sentes et le cas �ch�ant, ajouter �\verb|.0|� comme partie d�cimale. Une fois ceci fait, elle passera la main � une macro auxiliaire \verb|\decadd@i|, � arguments d�limit�s. La macro �\ifnodecpart, utilis�e par �\formatnum, sera charg�e de tester si le point est pr�sent ou pas.

\showcode/\catcode`@11
\def\ifnodecpart#1{\ifnodecpart@i#1.\@nil}��*\ifnodecpart�
\def\ifnodecpart@i#1.#2\@nil{\ifempty{#2}}��*\ifempty�
\def\decadd#1#2{% #1 et #2=nombre � additionner��*\decadd�
       \ifnodecpart{#1}% si #1 est un entier��*\ifnodecpart�
               {\ifnodecpart{#2}% et #2 aussi, les additionner avec \numexpr��*\ifnodecpart�
                       {\number\numexpr#1+#2\relax}%�\idx*\numexpr�
                       {\decadd@i#1.0\@nil#2\@nil}% sinon, ajouter ".0" apr�s #1
               }
               {\ifnodecpart{#2}% si #1 a une partie enti�re mais pas #2��*\ifnodecpart�
                       {\decadd@i#1\@nil#2.0\@nil}% ajouter ".0" � #2
                       {\decadd@i#1\@nil#2\@nil}% sinon, les 2 parties enti�res sont pr�sentes
               }%
}
\def\decadd@i#1.#2\@nil#3.#4\@nil{% affiche les parties enti�res et d�cimales re�ues
       $x_a=#1\quad y_a=#2\qquad x_b=#3\quad y_b=#4$
}
\catcode`@12
a) \decadd{5}{9.4}\par
b) \decadd{-3.198}{-6.02}\par
c) \decadd{0.123}{123}��*\decadd�/%
\def\olddecadd#1#2{% #1 et #2=nombre � additionner
       \ifnodecpart{#1}% si #1 est un entier��*\ifnodecpart�
               {\ifnodecpart{#2}% et #2 aussi, les additionner avec \numexpr��*\ifnodecpart�
                       {\number\numexpr#1+#2\relax}%
                       {\decadd@i#1.0\@nil#2\@nil}% sinon, ajouter ".0" apr�s #1
               }
               {\ifnodecpart{#2}% si #1 a une partie enti�re mais pas #2��*\ifnodecpart�
                       {\decadd@i#1\@nil#2.0\@nil}% ajouter ".0" � #2
                       {\decadd@i#1\@nil#2\@nil}% sinon, les 2 parties enti�res sont pr�sentes
               }%
}

\subsection{Rendre les parties d�cimales de m�me longueur}
Venons-en maintenant � la partie la plus complexe. Nous allons programmer la �\addzeros qui va se charger d'ajouter des 0 inutiles � la fin d'un des deux nombres \verb|#2| ou \verb|#4| re�us par \verb|\decadd@i| pour que ces parties d�cimales aient le m�me nombre de chiffres. Afin de rester purement d�veloppable, cette macro va utiliser le syst�me des � arguments r�servoirs �. Son texte de param�tre sera

\centrecode-#1#2/#3.#4#5/#6.#7/-

\noindent o� :

\begin{itemize}
       \item \verb|#1| est le premier chiffre de $y_a$ et \verb|#2| les chiffres restants;
       \item \verb|#3| est le r�servoir contenant les chiffres de $y_a$ d�j� examin�s;
       \item \verb|#4|, \verb|#5| et \verb|#6| jouent le m�me r�le pour $y_b$ que \verb|#1|, \verb|#2| et \verb|#3| pour $y_a$;
       \item \verb|#7| est un r�servoir recevant le seuil de retenue : il contient 1 au d�but et un �\verb|0|� est ajout� � chaque it�ration.
\end{itemize}

L'id�e directrice est que le point d'arr�t se produit lorsque les deux arguments d�limit�s \verb|#2| et \verb|#5| sont vides. Dans le cas contraire, � chaque it�ration, \verb|#1| passe en fin de \verb|#3|, \verb|#4| passe en fin de \verb|#6| et un 0 est ajout� � \verb|#7|. Si un des arguments \verb|#2| ou \verb|#5| devient vide, il faut alimenter l'argument non d�limit� \verb|#1| ou \verb|#4| qui le pr�c�de avec 0.

Pour se repr�senter la situation, imaginons que les nombres $y_a=457$ et $y_b=689714$ soient trait�s par �\addzeros et que l'appel suivant ait �t� fait :

\centrecode-\addzeros457/.689714/.1-�*\addzeros

\noindent Le chiffre 4 et le chiffre 6 vont �tre transf�r�s dans les r�servoirs et un 0 sera ajout� apr�s le 1. L'appel r�cursif apr�s la premi�re it�ration sera donc

\centrecode-\addzeros57/4.89714/6.10-

\noindent Puis le processus identique sera effectu� et l'appel suivant sera

\centrecode-\addzeros7/45.9714/68.100-�*\addzeros

Comme il ne reste plus aucun chiffre apr�s le 7 (ce qui signifie que l'argument d�limit� \verb|#2| est vide), le 7 sera transf�r� dans le r�servoir, mais un 0 sera mis � sa place pour les appels suivants. Ces appels seront donc:

\begin{centrage}\small
       \verb|\addzeros0/457.714/689.1000|\par�*\addzeros
       \verb|\addzeros0/4570.14/6897.10000|\par
       \verb|\addzeros0/45700.4/68971.100000|�*\addzeros
\end{centrage}

Enfin, comme il ne reste plus de chiffre ni apr�s $y_a$ ni apr�s $y_b$, le \idx{point d'arr�t} est atteint : \verb|#2| et \verb|#5| sont vides. La macro transf�re une derni�re fois un 0 en fin de r�servoir \verb|#3|, transf�re aussi le 4 en fin de r�servoir \verb|#5| et ajoute un dernier 0 au dernier argument pour mettre dans le flux de lecture de \TeX{} les trois arguments suivants :

\centrecode-{457000}{689714}{1000000}-

Pour comprendre le cheminement des arguments, la macro affiche ici ce qu'elle fait :

\showcode|\def\addzeros#1#2/#3.#4#5/#6.#7/{%��*\addzeros�
       Arguments re�us : #1#2/#3.#4#5/#6.#7/\par% afficher ce que la macro re�oit
       \ifempty{#2}% si #1 est le dernier chiffre de y��*\ifempty�
               {\ifempty{#5}% et si #4 est le dernier chiffre de y2��*\ifempty�
                       {R�sultat final : \detokenize{{#3#1}{#6#4}{#70}}}% afficher le r�sultat final
                       {\addzeros0/#3#1.#5/#6#4.#70/}% sinon alimenter #1 avec un 0
               }
               {\ifempty{#5}% si #4 est le dernier chiffre de y2��*\ifempty�
                       {\addzeros#2/#3#1.0/#6#4.#70/}% alimenter #4 avec un 0
                       {\addzeros#2/#3#1.#5/#6#4.#70/}% #2 et #5 non vides
               }%
}
\addzeros457/.689714/.1/��*\addzeros�|

\subsection{Additionner s�par�ment}
Int�ressons-nous tout d'abord � la macro qui va donner le signe du nombre d�cimal. Si $x$ est sa partie enti�re, la macro �\sgn, vue pr�c�demment ne va pas convenir. Voici quel �tait son code :

\centrecode|\def\sgn#1{\ifnum#1<0 -\fi}|�*\sgn

Par exemple, si le d�cimal � examiner vaut $-0.123$, alors, la partie enti�re $x=-0$ et \verb|\sgn{-0}| ne revoit pas un signe n�gatif. Pour se pr�munir de cette erreur, la macro �\true@sgn que nous allons employer renverra un signe �\verb|-|� lorsque son argument commence par �\verb|-|�. Pour ce faire, elle se contente de tester le signe de son argument une fois lui avoir ajout� le chiffre 1 en derni�re position :

\centrecode|\def\true@sgn#1{\ifnum#11<\z@-\fi}|\idx*\z@�*\true@sgn

Il faut rester conscient qu'ajouter le chiffre 1 au nombre \verb|#1| et �valuer le tout avec \verb|\ifnum| n'est pas anodin. Le r�sultat �valu� par \verb|\ifnum|, qui est $\verb|#1|\times10\pm1$, doit �tre dans l'intervalle $I=[-2^{31}+1\;\string;\;2^{31}-1]$. Par cons�quent, l'intervalle dans lequel doit se trouver \verb|#1| est plus �troit que $I$. M�me si cet �cueil n'est pas vraiment g�nant, on aurait pu s'en pr�munir en testant si \verb|#1| commence par �\verb|-|�.

La macro \verb|\decadd@i| va utiliser le fait que \idx\romannumeral\verb|-`\@|, plac� avant la macro �\addzeros, lance le d�veloppement maximal pour obtenir les trois arguments finaux. Elle appellera donc une nouvelle macro \verb|\decadd@ii|, admettant ces trois arguments auxquels nous rajouterons, en 4\ieme{} et 5\ieme{} arguments, les parties enti�res. La macro \verb|\decadd@ii|, qui re�oit ces 5 arguments, se contentera d'additionner les parties d�cimales entre elles (apr�s avoir leur avoir ajout� le signe des parties enti�res) ainsi que les parties enti�res entre elles et transmettra le tout � la macro suivante \verb|\decadd@iii| :

\showcode|\catcode`\@11
\def\addzeros#1#2/#3.#4#5/#6.#7/{%��*\addzeros�
       \ifempty{#2}% si #1 est le dernier chiffre de y1��*\ifempty�
               {\ifempty{#5}% et si #4 est le dernier chiffre de y2��*\ifempty�
                       {{#3#1}{#6#4}{#70}}% redonner les 3 arguments
                       {\addzeros0/#3#1.#5/#6#4.#70/}% sinon alimenter #1 avec un 0
               }
               {\ifempty{#5}% si #4 est le dernier chiffre de y2��*\ifempty�
                       {\addzeros#2/#3#1.0/#6#4.#70/}% alimenter #4 avec un 0
                       {\addzeros#2/#3#1.#5/#6#4.#70/}% #2 et #5 non vides
               }%
}
\def\decadd#1#2{% #1 et #2=nombre � additionner��*\decadd�
       \ifnodecpart{#1}��*\ifnodecpart�
               {\ifnodecpart{#2}{\number\numexpr#1+#2\relax}{\decadd@i#1.0\@nil#2\@nil}}
               {\ifnodecpart{#2}{\decadd@i#1\@nil#2.0\@nil}{\decadd@i#1\@nil#2\@nil}}%��*\ifnodecpart�
}
\def\decadd@i#1.#2\@nil#3.#4\@nil{%
       \expandafter\decadd@ii
                       \romannumeral-`\0\addzeros#2/.#4/.1/% se d�veloppe en 3 arguments�\idx*\romannumeral�*\addzeros�
                       {#1}
                       {#3}%
}
\def\decadd@ii#1#2#3#4#5{%
% #1 et #2=parties d�cimales (m�mes longueurs);
% #3=seuil de retenue; #4 et #5=parties enti�res
       \exptwoargs{\decadd@iii{#3}}% envoyer le seuil de retenue tel quel��*\exptwoargs�
               % sommer les parties d�cimales sign�es
               {\number\numexpr\true@sgn{#4}#1+\true@sgn{#5}#2\relax}%�\defline\aaa�*\true@sgn�
               % et les parties enti�res
               {\number\numexpr#4+#5\relax}%
}
\def\decadd@iii#1#2#3{%
       seuil de retenue = #1 \qquad nombre = "#3"."#2"%
}
\catcode`\@12
a) \decadd{6.7}{3.498}\par
b) \decadd{1.67}{-4.9}\par
c) \decadd{3.95}{2.0005}\par
d) \decadd{1.007}{2.008}\par
e) \decadd{-7.123}{3.523}��*\decadd�|

\subsection{Correctement g�rer les 0}
Les deux derniers cas montrent que les 0 au d�but de la partie d�cimale sont supprim�s par le \idx\number de la ligne \no\aaa{} tandis que les 0 inutiles de la fin sont conserv�s. C'est exactement le comportement inverse de celui qui est souhait� ! Afin de r�tablir une partie d�cimale ayant des 0 l� o� il faut, nous devons �crire une macro

\centrecode-\format@dec{<partie d�cimale>}{<seuil de retenue>}-

\noindent qui est purement d�veloppable et qui supprime les 0 de droite tout en ajoutant les 0 de gauche.
\grandsaut

Si par exemple, on obtient une partie d�cimale �gale � 710 avec un seuil de retenue de 100000, la partie d�cimale avait 5 chiffres, c'est-�-dire 00710 qui se doit �tre transform�e en 0071. Pour parvenir � ses fins, la macro \verb|\format@dec| va d'abord ajouter le seuil de retenue � la valeur absolue de la partie d�cimale :

\[710+100000=100710\]

\noindent Elle va ensuite inverser le r�sultat avec �\reverse

\[017001\]

\noindent Puis soumettre le nombre obtenu � \idx\number ce qui aura pour effet de supprimer les 0 de d�but (qui �taient ceux de fin)

\[17001\]

\noindent Ensuite, il faut � nouveau inverser le r�sultat pour r�tablir l'ordre de chiffres

\[10071\]

\noindent Enfin, il reste � manger le "1" en premi�re position avec \verb|\gobone| pour obtenir $0071$. L'ordre des op�rations est critique :

\showcode/\catcode`\@11
\def\format@dec#1#2{% #1=partie d�cimale #2=seuil de retenue
       \expandafter\gobone% le \gobone agira en dernier,
               \romannumeral-`\0% mais avant, tout d�velopper�\idx*\romannumeral�
               \expandafter\reverse\expandafter% et retarder le \reverse de fin��*\reverse�
                       % pour d�velopper son argument qui
                       {\number% d�veloppe tout et �value avec \number
                               \expandafter\reverse\expandafter% l'inversion de��*\reverse�
                               {\number\numexpr\abs{#1}+#2\relax}% |#1|+#2��*\abs�
                       }%
}
a) \format@dec{710}{100000}\par
b) \format@dec{6}{100}\par
c) \format@dec{-12300}{1000000}
\catcode`\@12/

\subsection{Calculer le r�sultat}
Reprenons notre chemin dans le texte de remplacement de \verb|\decadd@iii|. Elle doit effectuer les �ventuelles modifications sur les parties enti�res et d�cimales selon que $x$ et $y$ sont de signes contraires et sinon, effectuer d'autres modifications si $|y|\geqslant10^n$. Ces tests ne pr�sentent pas de difficult� et seront faits avec \tidx{ifnum}. � la toute fin, la macro \verb|\decadd@iv| re�oit 3 arguments de \verb|\decadd@iii|, la partie enti�re, la partie d�cimale et le seuil de retenue. Cette macro se chargera d'afficher \verb|#1|, et si \verb|#2| est diff�rent de 0, le point d�cimal ainsi que la partie d�cimale format�e avec \verb|\format@dec|. Pour que le 2-d�veloppement de �\decadd donne le r�sultat, le d�veloppement maximal sera engag� via \idx\romannumeral d�but de la macro. Comme rien n'est dirig� vers l'affichage jusqu'� \verb|\decadd@iv|, ce d�veloppement sera en vigueur � l'entr�e de cette macro. Il faut ensuite le propager pour qu'il atteigne \verb|\format@dec| avant que la partie enti�re ne soit affich�e.

Voici le code complet :

\showcode|\catcode`@11
\def\true@sgn#1{\ifnum#11<\z@-\fi}�\idx*\z@�*\true@sgn�
\def\decadd#1#2{% #1 et #2=nombre � additionner��*\decadd�
       \romannumeral-`\.% tout d�velopper jusqu'� l'affichage du nombre (\decadd@iv)
       \ifnodecpart{#1}% si #1 est un entier��\ifnodecpart�
               {\ifnodecpart{#2}% et #2 aussi, les additionner avec \numexpr��*\ifnodecpart�
                       {\numexpr#1+#2\relax}%
                       {\decadd@i#1.0\@nil#2\@nil}% sinon, ajouter ".0" apr�s #1
               }
               {\ifnodecpart{#2}% si #1 a une partie enti�re mais pas #2��*\ifnodecpart�
                       {\decadd@i#1\@nil#2.0\@nil}% ajouter ".0" � #2
                       {\decadd@i#1\@nil#2\@nil}% sinon, les 2 parties enti�res sont pr�sentes
               }%
}
\def\decadd@i#1.#2\@nil#3.#4\@nil{%
       \expandafter\decadd@ii
                       \romannumeral-`\0\addzeros#2/.#4/.10/% se d�veloppe en 3 arguments�\idx*\romannumeral�*\addzeros�
                       {#1}
                       {#3}%
}
\def\decadd@ii#1#2#3#4#5{%
% #1 et #2=parties d�cimales (m�mes longueurs)
% #3=seuil de retenue; #4 et #5=parties enti�res
       \exptwoargs{\decadd@iii{#3}}% envoyer le seuil de retenue tel quel��*\exptwoargs�
               % sommer les parties d�cimales sign�es
               {\number\numexpr\true@sgn{#4}#1+\true@sgn{#5}#2\relax}%�\defline\aaa�*\true@sgn�
               % et les parties enti�res
               {\number\numexpr#4+#5\relax}%
}
\def\decadd@iii#1#2#3{% #1=seuil de retenue #2=partie d�cimale #3= partie enti�re
       \ifnum\true@sgn{#2}\true@sgn{\ifnum#3=\z@#2\else#3\fi}1=-1 % si les signes sont
                                                                  % diff�rents�\idx*\z@�*\true@sgn�
       \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
               {\exptwoargs\decadd@iv% transmettre les arguments modifi�s :��*\exptwoargs�
                       {\number\numexpr#3-\true@sgn{#3}1}% #3:=#3-sgn(#3)1�\idx*\numexpr�
                       {\number\numexpr#2-\true@sgn{#2}#1}% #2:=#2-sgn(#2)10^n��*\true@sgn�
                       {#1}%
               }% si les signes sont �gaux
               {\ifnum\abs{#2}<#1 % et si abs(y)<10^n��*\abs�
               \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
                       {\decadd@iv{#3}{#2}{#1}% tranmettre les arguments tels quels
                       }
                       {\exptwoargs\decadd@iv% sinon��*\exptwoargs�
                               {\number\numexpr#3+\true@sgn{#3}1}% #3:=#3+sgn(#3)1
                               {\number\numexpr#2-\true@sgn{#2}#1}% #2:=#2-sgn(#2)10^n
                               {#1}%
                       }%
               }%
}
\def\decadd@iv#1#2#3{% affiche le d�cimal "#1.#2"
       % le d�veloppement maximal initi� par le \romannumeral de \decadd est actif
       \ifnum#1=\z@\ifnum#2<\z@% si #1=0 et #2<0�\idx*\z@�
               \expandafter\expandafter\expandafter% transmettre le d�veloppement � \number
               -% puis afficher le signe "-"
       \fi\fi
       \number#1% affiche #1 qui est la somme des parties enti�res
       % poursuivre le d�veloppement initi� par \number
       \unless\ifnum#2=\z@% si la partie d�cimale est diff�rente de 0�\tidx*{unless}�
               \antefi% se d�barrasser de \fi��*\antefi�
               \expandafter.% afficher le "." d�cimal apr�s avoir
               \romannumeral-`\0\format@dec{#2}{#3}% correctement g�r� les 0 de #2�\idx*\romannumeral�
       \fi
}
\def\addzeros#1#2/#3.#4#5/#6.#7/{%��*\addzeros�
       \ifempty{#2}% si #1 est le dernier chiffre de y1��*\ifempty�
               {\ifempty{#5}% et si #4 est le dernier chiffre de y2
                       {{#3#1}{#6#4}{#7}}% redonner les 3 arguments
                       {\addzeros0/#3#1.#5/#6#4.#70/}% sinon alimenter #1 avec un 0��*\addzeros�
               }
               {\ifempty{#5}% si #4 est le dernier chiffre de y2��*\ifempty�
                       {\addzeros#2/#3#1.0/#6#4.#70/}% alimenter #4 avec un 0
                       {\addzeros#2/#3#1.#5/#6#4.#70/}% #2 et #5 non vides��*\addzeros�
               }%
}
\def\format@dec#1#2{% #1=partie d�cimale #2=seuil de retenue
       \expandafter\gobone% le \gobone agira en dernier,
               \romannumeral-`\0% mais avant, tout d�velopper�\idx*\romannumeral�
               \expandafter\reverse\expandafter% et retarder le \reverse de fin��*\reverse�
                       % pour d�velopper son argument qui
                       {\number% d�veloppe tout et �value avec \number
                               \expandafter\reverse\expandafter% l'inversion de��*\reverse�
                               {\number\numexpr\abs{#1}+#2\relax}% abs(#1)+#2��*\abs\idx*\z@�
                       }%
}
\catcode`@12
a) $-3.78+1.6987=\decadd{-3.78}{1.6987}$\par
b) $3.56-3.06=\decadd{3.56}{-3.06}$\par
c) $4.125+13.49=\decadd{4.125}{13.49}$\par
d) $-0.99+1.005=\decadd{-0.99}{1.005}$\par
e) $16.6-19.879=\decadd{16.6}{-19.879}$\par
f) $5.789-0.698=\decadd{5.789}{-0.698}$\par
g) $0.123-0.123=\decadd{0.123}{-0.123}$\par
h) $3.14-16.4912=\decadd{3.14}{-16.4912}$\par
i) $0.1-0.98=\decadd{0.1}{-0.98}$\par
j) $2.43+7.57=\decadd{2.43}{7.57}$\par
h) \edef\foo{\decadd{1.23}{9.78}}\meaning\foo\par
j) \detokenize\expandafter\expandafter\expandafter{\decadd{3.14}{-8.544}}��*\decadd�|�*\decadd[|)]%

\chapter{Primitives sp�cifiques � un moteur}
Les nouvelles primitives introduites par \eTeX{} font d�sormais partie du vocabulaire reconnaissable par tous les moteurs (pdf\TeX, \XeTeX{} et lua\TeX).

Cette compatibilit� est malheureusement cass�e par des primitives \emph{sp�cifiques} aux moteurs, c'est-�-dire prises en charge par lui seul. On franchit l� une ligne de d�marcation importante pour la compatibilit� puisqu'utiliser ces primitives rend obligatoire la compilation avec un moteur sp�cifique. Beaucoup de ces primitives sp�cifiques sont certes \emph{tr�s} pratiques, mais il est utile de se demander si les fonctionnalit�s additionnelles qu'elles apportent valent une rupture de compatibilit�.
\grandsaut

Il n'est �videmment pas question de d�crire ici toutes les primitives sp�cifiques � tous les moteurs. Cela prendrait beaucoup de place (pdf\TeX{} en a plus de 130 !) pour un int�r�t limit�, car la plupart sont correspondent � un besoin tr�s pr�cis et sont d'une utilisation assez pointue. Les documentations des moteurs en dressent la liste exhaustive, en pr�cisent la syntaxe et d�crivent les fonctionnalit�s offertes. Nous nous contenterons de pr�senter deux primitives de pdf\TeX{}, moteur utilis� pour compiler le code source de ce livre.

Le lecteur pourra, s'il le souhaite, se plonger dans la documentation de son moteur pr�f�r�, explorer les primitives qu'il offre et pourquoi pas, les utiliser pour ses besoins propres. Il faut cependant garder � l'esprit que ces primitives imposant un moteur sont d�conseill�es si le code source a vocation � �tre diffus� et compil� par d'autres personnes non avis�es de la rupture de compatibilit�.

\section{Comparer deux textes avec \texttt{\char`\\ pdfstrcmp}}\idx*[|(]{comparer des textes}
La primitive purement d�veloppable \idx*\pdfstrcmp

\centrecode-\pdfstrcmp{<texte 1>}{<texte 2>}-

\noindent permet de comparer les deux textes. Avant qu'elle n'entre en jeu, cette primitive d�veloppe au maximum ses deux arguments et les d�tokenize. \emph{Elle ne tient donc pas compte des catcodes} contrairement au test \verb|\ifx| :

\centrecode-\def\foo{<texte 1>} \def\bar{<texte 2>}
\ifx\foo\bar<code vrai>\else<code faux>\fi-

La primitive \idx\pdfstrcmp se d�veloppe en �\verb|0|� si tes textes sont �gaux, en �\verb|-1|� si le \verb|<texte 1>| vient avant le \verb|<texte 2>| et en �\verb|1|� s'il vient apr�s. Le classement des  textes se fait en fonction des codes ASCII des caract�res, pris successivement de gauche � droite jusqu'� ce qu'une diff�rence apparaisse.

\showcode/a) \pdfstrcmp{foo}{bar}\qquad�\idx*\pdfstrcmp�
b) \pdfstrcmp{bar}{foo}\qquad
c) \def\foo{ABC}\pdfstrcmp{\foo}{ABC}\qquad
d) \edef\foo{\string_}\pdfstrcmp{1_2}{1\foo2}\qquad
e) \pdfstrcmp{\string\relax}{\relax}�\idx*\string\idx*\pdfstrcmp�/

La derni�re comparaison est fausse, car �\idx\detokenize\verb|{\relax}|� se d�veloppe en \verb*|\relax | alors que \idx\string n'introduit pas d'espace apr�s les s�quences de contr�le. Les textes �\verb*|\relax |� et �\verb|\relax|� ne sont pas �gaux.

Cette primitive dispose d'un �quivalent pour le moteur \XeTeX{}\idx*{moteur!xetex}, mais elle ne porte pas le m�me nom : \verb|\strcmp|.\idx*[|)]{comparer des textes}

\section{Mesurer le temps}\idx*[|(]{chronom�trer le temps d'ex�cution}
Voici un deuxi�me exemple de primitive sp�cifique � pdf\TeX{}, \idx\pdfelapsedtime qui permet de mesurer le temps de compilation. Cette primitive est de type entier et contient le nombre de secondes \emph{d'�chelle} �coul�es depuis le d�but de la compilation : 1 \idx{seconde d'�chelle} vaut $\frac1{65536}$ de seconde tout comme un \idx{point d'�chelle} vaut $\frac1{65536}$ de point. Convertir les secondes d'�chelle en secondes revient � convertir les sp\idx*{sp (unit�)} en pt\idx*{pt (unit�)}, ce que permet tr�s facilement la macro �\convertunit.

\showcode/\edef\tempcompil{\number\pdfelapsedtime}%�\idx*\pdfelapsedtime�
Depuis le d�but de la compilation, il s'est �coul� \tempcompil{} secondes d'�chelle,�\idx*{seconde d'�chelle}�
soit \convertunit{\tempcompil sp}{pt} secondes.��*\convertunit�/

\Qu elle que soit la dur�e de compilation, l'entier \idx\pdfelapsedtime ne peut exc�der $2^{31}-1$ qui sera sa limite sup�rieure et qui repr�sente \numprint{32768} secondes.

La primitive \idx\pdfresettimer, qui remet � 0 le compteur interne de secondes d'�chelle\idx*{seconde d'�chelle}, ouvre des perspectives int�ressantes. Coupl�e � \idx\pdfelapsedtime, elle permet de mesurer avec pr�cision la dur�e qui s'�coule entre deux moments arbitraires de la compilation. Nous allons ici mettre � profit cette possibilit� pour mesurer la vitesse relative entre la boucle \idx\loop...\idx\repeat (celle de \TeX{} puis celle de \LaTeX) et la boucle �\for, dont la programmation a �t� abord�e � partir de la page \no\pageref{for}. Chaque boucle sera parcourue 100000 fois, mais, afin de mesurer la vitesse de la boucle elle-m�me, aucun code ne sera ex�cut� � chaque it�ration :

\showcode/%%%%%%%%%% definition de \loop...\repeat comme plain-TeX %%%%%%%%%%
\def\loop#1\repeat{\def\body{#1}\iterate}�\idx*\loop\idx*\repeat�
\def\iterate{\body \let\next\iterate \else\let\next\relax\fi \next}�\idx*\iterate�
\let\repeat=\fi�\idx*\repeat�
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcount\testcnt�\idx*\newcount�
\pdfresettimer% remet le compteur � 0�\idx*\pdfresettimer�
       \testcnt=0
       \loop % Test no 1�\idx*\loop�
               \ifnum\testcnt<100000 \advance\testcnt 1 �\idx*\advance�
       \repeat�\idx*\repeat�
Temps 1 = \convertunit{\pdfelapsedtime sp}{pt} s (boucle loop de \TeX)\par��*\convertunit\idx*\pdfelapsedtime�
%%%%%%%%%%%% definition de \loop...\repeat comme LaTeX %%%%%%%%%%%%
\def\loop#1\repeat{\def\iterate{#1\relax\expandafter\iterate\fi}%
 \iterate \let\iterate\relax}�\idx*\iterate�
\let\repeat\fi
\pdfresettimer% remet le compteur � 0�\idx*\pdfresettimer�
       \testcnt=0
       \loop % Test no 2�\idx*\loop�
               \ifnum\testcnt<100000
               \advance\testcnt 1 �\idx*\advance�
       \repeat�\idx*\repeat�
Temps 2 = \convertunit{\pdfelapsedtime sp}{pt} s (boucle loop de \LaTeX)\par��*\convertunit\idx*\pdfelapsedtime�
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pdfresettimer% remet le compteur � 0
       \for\ii=1 to 100000\do{}% Test no 3��*\for�
Temps 3 = \convertunit{\pdfelapsedtime sp}{pt} s (boucle for)��*\convertunit\idx*\pdfelapsedtime�/

Notre boucle �\for semble donc environ 3 fois plus lente que la boucle \idx\loop{}\linebreak[2]\verb|...|{}\linebreak[2]\idx\repeat de \LaTeX{} qui est la plus rapide. Il faut dire �\emph{semble}�, car l'incr�mentation ne se fait pas sur le m�me type de donn�e. La boucle �\for incr�mente le \emph{texte de remplacement} d'une macro tandis que dans le code ci-dessus, un \emph{compteur} est incr�ment� dans la boucle \idx\loop...\idx\repeat. Pour �tre strictement �quitable et pour �tre s�r de comparer les codes des deux boucles, la boucle \idx\loop...\idx\repeat doit imiter la boucle �\for et incr�menter le texte de remplacement d'une macro :

\showcode/%%%%%%%%%%%% definition de \loop...\repeat comme LaTeX %%%%%%%%%%%%
\def\loop#1\repeat{\def\iterate{#1\relax\expandafter\iterate\fi}%�\idx*\loop�
 \iterate \let\iterate\relax}�\idx*\iterate�
\let\repeat\fi�\idx*\repeat�
\pdfresettimer% remet le compteur � 0�\idx*\pdfresettimer�
       \def\ii{0}%
       \loop % Test no 1�\idx*\loop�
               \ifnum\ii<100000
               \edef\ii{\number\numexpr\ii+1\relax}%
       \repeat�\idx*\repeat�
Temps 1 = \convertunit{\pdfelapsedtime sp}{pt} s (boucle loop de \LaTeX)\par��*\convertunit\idx*\pdfelapsedtime�
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pdfresettimer% remet le compteur � 0�\idx*\pdfresettimer�
       \for\ii=1 to 100000\do{}% Test no 2��*\for�
Temps 2 = \convertunit{\pdfelapsedtime sp}{pt} s (boucle for)��*\convertunit\idx*\pdfelapsedtime�/

La diff�rence de vitesse est maintenant plus t�nue, de l'ordre de 30\%, ce qui semble une contrepartie acceptable en regard des fonctionnalit�s d'imbrication qu'offre �\for par rapport � \idx\loop...\idx\repeat. On en tire par ailleurs l'enseignement qu'incr�menter un compteur est \emph{plus rapide} que de recourir � \idx\numexpr et \idx\edef pour incr�menter un entier contenu dans le texte de remplacement d'une macro. En voici la d�monstration :

\showcode/\newcount\testcnt�\idx*\newcount�
\pdfresettimer�\idx*\pdfresettimer�
\testcnt=0
\for\ii=1 to 100000\do{\advance\testcnt1 }��*\for�
Temps 1 : \convertunit{\pdfelapsedtime sp}{pt} s (incr�mentation compteur)��*\convertunit\idx*\pdfelapsedtime�

\pdfresettimer�\idx*\pdfresettimer�
\def\foo{0}%
\for\ii=1 to 100000\do{\edef\foo{\number\numexpr\foo+1\relax}}%��*\for�
Temps 2 : \convertunit{\pdfelapsedtime sp}{pt} s (incr�mentation du texte de remplacement)��*\convertunit\idx*\pdfelapsedtime�/

On peut ainsi comparer les vitesses entre les variantes d'un algorithme afin de trouver celle qui optimise la vitesse d'ex�cution.\idx*[|)]{chronom�trer le temps d'ex�cution}

\chapter{Recueil des r�gles}\label{recapregle}
Les r�gles se trouvant dans les cadres gris�s ont �t� assez nombreuses (il y en a exactement \number\csname cnt@regle\endcsname). Les voici rassembl�es ici.
\makeatletter
\renewcommand\tidx@i[2][]{% #2 est le nom de la primitive SANS le caract�re d'�chappement
       \print@idx{\texttt{\char92 #2}}%
}
\makeatother
\input regles.txt
%|                                                                            |
%|                                Fin annexes                                 |
%|____________________________________________________________________________|
\chapter*{Bibliographie}
\addcontentsline{toc}{part}{Bibliographie}

\begin{enumerate}[leftmargin=*,itemsep=5pt,topsep=10pt]
       \item \textsc{D.E. Knuth}. Le \TeX book, Vuibert, 2003.\par
       {\footnotesize\verb|http://www.vuibert.fr/ouvrage-9782711748198-le-texbook.html|}
       \item \textsc{D.E. Knuth}. \TeX{} The Program.\par
       {\footnotesize\verb|http://tug.org/texlive/devsrc/Build/source/texk/web2c/tex.web|}
       \item \textsc{V. Eijkhout}. \TeX{} by Topic, Addison-Wesley, 1992.\par
       {\footnotesize\verb|http://www.eijkhout.net/texbytopic/texbytopic.html|}
       \item \textsc{P.W. Abrahams \& K. Hargreaves \& K. Berry}. \TeX{} pour l'impatient.\par
       {\footnotesize\verb|http://ctan.mirrorcatalogs.com/info/impatient/fr/fbook.pdf|}
       \item \textsc{J. Braams \& D. Carlisle \& A. Jeffrey \& L. Lamport \&\endgraf F.Mittelbach \&  C. Rowley \& R. Sch\"opf}. The \LaTeXe{} sources\par
       {\footnotesize\verb|http://www.tug.org/texlive/Contents/live/texmf-dist/doc/latex/base/source2e.pdf|}
       \item \textsc{E. Gregorio}. Appunti di programmazione in \LaTeX{} e \TeX.\par
       {\footnotesize\verb|http://profs.scienze.univr.it/~gregorio/introtex.pdf|}
\end{enumerate}

% ____________________________________________________________________________
%|                                                                            |
%|                                   Index                                    |
%|                                                                            |
\cidx*[|voiraussi{mode math�matique}]\$%
\cidx*[|voiraussi{\texttt{\char92 halign}}]\&%
\idx*[|voiraussi{\texttt{\char92 chardef}}]\&
\cidx*[|voiraussi{\texttt{\char92 catcode} $\rightsquigarrow$ 13}]\\
\idx*[|voir{\texttt{\char`\^\char`\^M}}]{retour charriot}%
\idx*[|voiraussi{\texttt{\char92 loop}}]\body
\idx*[|voiraussi{\texttt{\char92 catcode} $\rightsquigarrow$ 13}]{caract�re actif}%
\idx*[|voiraussi{\texttt{\char92 hyphenchar}}]{caract�re de coupure}%
\idx*[|voiraussi{\texttt{\char92 catcode} $\rightsquigarrow$ 0, �\texttt{\char92}�}]{caract�re d'�chappement}%
\idx*[|voiraussi{\texttt{\char92 endlinechar}, \texttt{\char92 newlinechar}}]{caract�re de fin de ligne}%
\idx*[|voir{\texttt{\char92 catcode}}]{code de cat�gorie}
\idx*[|voiraussi{\texttt{\char92 uccode}, \texttt{\char92 uppercase}}]{code majuscule}
\idx*[|voiraussi{\texttt{\char92 lccode}, \texttt{\char92 lowercase}}]{code minuscule}
\idx*[|voiraussi{\texttt{\char92 edef}}]{code purement d�veloppable}
\idx*[|voiraussi{\texttt{\char92 /}}]{correction d'italique}
\idx*[|voiraussi{\texttt{\char92 vsplit}}]{couper une boite verticale}
\idx*[|voiraussi{\texttt{\char92 llap}, \texttt{\char92 rlap}, \texttt{\char92 hfuzz},\texttt{\char92 vfuzz}}]{d�bordement de boite}
\idx*[|voir{\texttt{\char92 moveleft}, \texttt{\char92 moveright}, \texttt{\char92 lower}, \texttt{\char92 raise}}]{d�placement de boite}
\idx*[|voiraussi{\texttt{\char92 edef}, \texttt{\char92 csname}, \texttt{\char92 romannumeral}, \texttt{\char92 write}, nombre $\rightsquigarrow$ d�finition}]{d�veloppement maximal}
\idx*[|voiraussi{\texttt{\char92 fontdimen}}]{dimensions de fonte}
\idx*[|voiraussi{\texttt{\char92 long}, \texttt{\char92 par}}]\endgraf
\idx*[|voir{compteur, nombre}]{entier}
\idx*[|voiraussi{\texttt{\char`\^\char`\^J}}]{fin de ligne}%
\idx*[|voir{macro fille}]{imbrication de macros}
\idx*[|voiraussi{\texttt{\char92 write}, \texttt{\char92 openout}}]{\immediate}%
\idx*[|voir{\texttt{\char92 loop}}]{\iterate}%
\idx*[|voir{\texttt{\char92 loop}, \texttt{\char92 for}$^\star$, \texttt{\char92 doforeach}$^\star$}]{boucle}
\idx*[|voir{�\texttt{\char`@}�}]{macro priv�e}
\idx*[|voiraussi{boite $\rightsquigarrow$ g�om�trie}]{point de r�f�rence}
\idx*[|voiraussi{sp (unit�)}]{point d'�chelle}
\index{registre!entier|voir{compteur}}
\idx*[|voir{\texttt{\char92 meaning}, \texttt{\char92 show}}]{signification d'un token}
\idx*[|voir{\texttt{\char`\^\char`\^J}}]{tabulation}%
\idx*[|voiraussi{\texttt{\char92 relax} $\rightsquigarrow$ sp�cial}]{test incomplet}%
\idx*[|voiraussi{\texttt{\char92 litterate}$^\star$}]{verbatim}%
\idx*[|voiraussi{\texttt{\char92 let}}]{caract�re implicite}%
\cidx*[ (notation hexad�cimale)|voiraussi{nombre $\rightsquigarrow$ d�finition}]\"
\cidx*[ (notation octale)|voiraussi{nombre $\rightsquigarrow$ d�finition}]\'
\makeatletter
\idx*[|voiraussi{\texttt{\char92 input}}]\@@input
\makeatother
\cidx*[ (notation octale)|voiraussi{nombre $\rightsquigarrow$ d�finition}]\`
\idx*[!implicite|voiraussi{\texttt{\char92 bgroup}, \texttt{\char92 egroup}}]{accolade}
\idx*[|voiraussi{\texttt{\char92 hbadness}, \texttt{\char92 vbadness}}]{boite insuffisamment remplie}


\indexprologue{L'index ci-dessous liste les commandes et les notions abord�es dans le livre. Les commandes, qu'elles soient primitives ou macros, sont class�es alphab�tiquement sans tenir compte du caract�re d'�chappement �\texttt{\char`\\}�. Les commandes pr�c�d�es d'une �toile sont des primitives.

Certaines s�quences de contr�le ont �t� tr�s fr�quemment employ�es dans les codes expos�s dans ce livre. On trouve par exemple \texttt{\char`\\def}, \texttt{\char`\\expandafter}, \texttt{\char`\\catcode}, etc. Afin de ne pas inutilement surcharger l'index, seuls les num�ros de pages des premi�res apparitions ont �t� retenus. Ils sont suivis par � \ldots � qui symbolise les nombreux autres num�ros de page qui ont �t� omis.

Lorsqu'un renvoi � \textit{voir} � � une macro d�finie dans ce livre figure dans cet index, cette macro est suivie de �$^\star$�. L'index des macros d�finies dans ce livre se trouve � la page~\pageref{index.macros}.\par
}
\def\indexspace{\vskip 18pt plus 7pt minus 4pt \relax}
\small
\printindex

\normalsize
\indexprologue{\label{index.macros}L'index ci-dessous liste les macros d�finies dans ce livre. Toutes n'y figurent pas. � de rares exceptions pr�s, seules les macros \emph{publiques}, c'est-�-dire sans �\verb|@|�, y figurent.\par
}
\small
\printindex[macros]%

\normalsize
%|                                                                            |
%|                                 Fin index                                  |
%|____________________________________________________________________________|
\immediate\closeout\codewrite
\cleardoublepage\pagestyle{empty}\null\newpage
\null\vfill
\begin{centrage}
       \footnotesize
       Christian \textsc{Tellechea}

       ---

       D�p�t l�gal: septembre 2014
\end{centrage}%
\null
\vskip1cm\null
\end{document}