%\iffalse
% xfor.dtx generated using makedtx version 0.94b (c) Nicola Talbot
% Command line args:
%   -src "xfor.sty=>xfor.sty"
%   -doc "manual.tex"
%   -author "Nicola Talbot"
%   -dir "source"
%   xfor
% Created on 2007/8/21 17:28
%\fi
%\iffalse
%<*package>
%% \CharacterTable
%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%%   Digits        \0\1\2\3\4\5\6\7\8\9
%%   Exclamation   \!     Double quote  \"     Hash (number) \#
%%   Dollar        \$     Percent       \%     Ampersand     \&
%%   Acute accent  \'     Left paren    \(     Right paren   \)
%%   Asterisk      \*     Plus          \+     Comma         \,
%%   Minus         \-     Point         \.     Solidus       \/
%%   Colon         \:     Semicolon     \;     Less than     \<
%%   Equals        \=     Greater than  \>     Question mark \?
%%   Commercial at \@     Left bracket  \[     Backslash     \\
%%   Right bracket \]     Circumflex    \^     Underscore    \_
%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%%   Right brace   \}     Tilde         \~}
%</package>
%\fi
% \iffalse
% Doc-Source file to use with LaTeX2e
% Copyright (C) 2007 Nicola Talbot, all rights reserved.
% \fi
% \iffalse
%<*driver>
\documentclass[a4paper]{ltxdoc}
\usepackage{xfor}
\usepackage{ifthen}
\usepackage{alltt}
\usepackage[colorlinks,
            bookmarks,
            hyperindex=false,
            pdfauthor={Nicola L.C. Talbot},
            pdftitle={xfor: redefinition of '@for},
            pdfkeywords={LaTeX,package development}]{hyperref}

\CheckSum{117}
\PageIndex
\RecordChanges
\newcommand*{\sty}[1]{\textsf{#1}}

\begin{document}
\DocInput{xfor.dtx}
\end{document}
%</driver>
%\fi
%\MakeShortVerb{"}
%
% \title{xfor v1.03: Reimplementation of \cs{@for} to allow
%premature termination of the loop}
% \author{Nicola L.C. Talbot\\[10pt]
%School of Computing Sciences\\
%University of East Anglia\\
%Norwich. Norfolk\\
%NR4 7TJ. United Kingdom.\\
%\url{http://theoval.cmp.uea.ac.uk/~nlct/}}
%
%\date{21st August 2007}
%\maketitle
%\tableofcontents
%
%\section{Introduction}
%\changes{1.0}{2007 June 27}{Initial version}
%The \sty{xfor} package redefines \cs{@for} so that the loop can
%be prematurely terminated, akin to C/Java's \texttt{break} statement
%except that the loop will terminate at the \emph{end} of the
%current iteration. The syntax for \DescribeMacro{\@for}\cs{@for} 
%remains the same:
%\begin{quote}
%\cs{@for}\meta{cmd}":="\meta{list}"\do"\marg{body}
%\end{quote}
%where \meta{cmd} is a command name that is assigned to the current
%element of the list given by \meta{list} at each iteration.
%
%To terminate the loop at the end of the current
%iteration, use the command \DescribeMacro{\@endfortrue}\cs{@endfortrue}. 
%This command may be used anywhere in \meta{body}, but will only
%take effect at the end of the current iteration.
%The remainder of the list is stored in 
%\DescribeMacro{\@forremainder}\cs{@forremainder}. You can test 
%whether the loop was prematurely terminated using the conditional
%\DescribeMacro{\if@endfor}\cs{if@endfor}.
%
%As from version 1.02, there is also provision for looking ahead.
%At each iteration in the loop, the next element is stored in
%\cs{@xfor@nextelement}\DescribeMacro{\@xfor@nextelement}. 
%On the last iteration, this value
%will be \cs{@nil}, and so can be checked using
%\begin{verbatim}
% \ifx\@xfor@nextelement\@nnil
% % last iteration
% \else
% % not last iteration
% \fi
%\end{verbatim}
%
%\subsection{Example (ordered insertion)}
%
%Suppose you have list of sorted numbers stored in the command 
%\cs{mylist}, e.g.:
%\begin{verbatim}
%\def\mylist{1,3,5,7,8,12,15,20}
%\end{verbatim}
%and you want to insert a new value given by the command 
%\cs{newval}, e.g.
%\begin{verbatim}
%\def\newval{11}
%\end{verbatim}
%in the correct order. You can use \cs{@for} to iterate through
%each element in the sorted list, testing the value against the
%new value to be inserted. Once the new value has been inserted,
%the loop can be terminated, and any remaining elements can be
%appended to the new list. The following 
%defines the command \cs{insertinto}\marg{new val}\marg{list}
%which uses this method:
%\begin{verbatim}
% \newcommand{\insertinto}[2]{%
% \def\nlst{}%
% \@for\n:=#2\do{%
% % store new list in \toks@
% \expandafter\toks@\expandafter{\nlst}%
% % test current value against new value
% \ifnum\n>#1\relax
%   \edef\newstuff{\number#1,\n}%
%   % end for loop at the end of this iteration
%   \@endfortrue
% \else
%   \edef\newstuff{\n}%
% \fi
% % append new stuff to new list
% \ifx\nlst\@empty
%   \edef\nlst{\newstuff}%
% \else
%   \edef\nlst{\the\toks@,\newstuff}%
% \fi
% }%
% % check to see if for loop was prematurely terminated
% \if@endfor
%  % loop may have been terminated during final iteration, in
%  % which case \@forremainder is empty.
%  \ifx\@forremainder\@empty
%    % do nothing
%  \else
%    % loop prematurely ended, append remainder of original list
%    % to new list
%    \expandafter\toks@\expandafter{\nlst}%
%    \edef\nlst{\the\toks@,\@forremainder}%
%  \fi
% \else
%  % wasn't prematurely terminated, so new value hasn't been added
%  % add now.
%   \expandafter\toks@\expandafter{\nlst}%
%   \ifx\nlst\@empty
%     \edef\nlst{\number#1}%
%   \else
%     \edef\nlst{\the\toks@,\number#1}%
%   \fi
% \fi
% \let#2=\nlst
% }
%\end{verbatim}
%The \cs{insertinto} macro can then be used as follows:
%\begin{verbatim}
%\def\mylist{1,2,5,9,12,15,18,20}%
%\def\newval{11}%
%Original list: \mylist. New value: \newval.
%
%\insertinto{\newval}{\mylist}
%New list: \mylist.
%\end{verbatim}
%
%\subsection{Example (numerical insertion sort)}
%
%Care needs to be taken when nesting \cs{@for}-loops.
%Suppose you have a list of unsorted numbers, say
%\begin{verbatim}
%\def\mylist{4,2,7,1,10,11,20,15}
%\end{verbatim}
%and you want to sort the list in numerical order using an insertion
%sort method. To do this, a macro needs to be defined which iterates
%through each element in the unordered list, and the element 
%is then inserted into an ordered list. The previous example
%described the macro \cs{insertinto} which does this, but this results
%in nested \cs{@for} commands. The \cs{insertinto} command will need
%to be grouped to avoid errors:
%\begin{verbatim}
%\newcommand*{\insertionsort}[1]{%
%\def\sortedlist{}%
%\@for\val:=#1\do{{\insertinto{\val}{\sortedlist}}}%
%\let#1=\sortedlist
%}
%\end{verbatim}
%This won't work with the definition of \cs{insertinto} as
%given in the previous section, as the grouping causes the
%definition of the sorted list to be localised to that group.
%Replacing
%\begin{verbatim}
%\let#2=\nlst
%\end{verbatim}
%with
%\begin{verbatim}
%\global\let#2=\nlst
%\end{verbatim}
%at the end of the definition of \cs{insertinto} will fix that.
%
%\subsection{Example (looking ahead)}
%
%This example checks the next value to determine if the loop
%is on the last iteration, if it is, it does nothing, otherwise
%it does a semi-colon:
%\begin{verbatim}
%\makeatletter
%\def\mylist{1,2,3,4,5}%
%\@for\val:=\mylist\do{\val
%\ifx\@xfor@nextelement\@nnil \else ;\fi}
%\makeatother
%\end{verbatim}
%which produces:
%\makeatletter
%\def\mylist{1,2,3,4,5}\relax
%\@for\val:=\mylist\do{\val
%\ifx\@xfor@nextelement\@nnil \else ;\fi}
%\makeatother
%
% \StopEventually{\clearpage\phantomsection
%\addcontentsline{toc}{section}{Change History}
%\PrintChanges\phantomsection
%\addcontentsline{toc}{section}{Index}
%\PrintIndex}
%
%
%
%\section{The Code}
%\iffalse
%    \begin{macrocode}
%<*xfor.sty>
%    \end{macrocode}
%\fi
% Declare package:
%    \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{xfor}[2007/08/21 v1.03 (NLCT)]
%    \end{macrocode}
% Define a switch to determine if the for loop should be
% terminated:
%\begin{macro}{\if@endfor}
%    \begin{macrocode}
\newif\if@endfor
%    \end{macrocode}
%\end{macro}
% Redefine \cs{@for}, so that it resets \cs{if@endfor}
% and \cs{@forremainder}:
%\begin{macro}{\@for}
%    \begin{macrocode}
\long\def\@for#1:=#2\do#3{%
\@endforfalse
\def\@forremainder{}%
\expandafter\def\expandafter\@fortmp\expandafter{#2}%
\ifx\@fortmp\@empty
\else
  \expandafter\@forloop#2,\@nil,\@nil\@@#1{#3}%
\fi
}
%    \end{macrocode}
%\end{macro}
% Redefine \cs{@fornoop} to be a long command:
%\begin{macro}{\@fornoop}
%    \begin{macrocode}
\long\def\@fornoop#1\@@#2#3{}
%    \end{macrocode}
%\end{macro}
% Redefine \cs{@forloop} to check for \cs{if@endfor}:
%\begin{macro}{\@forloop}
%    \begin{macrocode}
\long\def\@forloop#1,#2,#3\@@#4#5{%
\def#4{#1}%
\ifx#4\@nnil
\else
 \@xfor@storenext#2,#3\@@%
 #5%
 \if@endfor
   \@iforgatherrest#2,#3%
 \else
   \def#4{#2}%
   \ifx#4\@nnil
   \else
     \@xfor@storenext#3,\@nil\@@%
     #5%
     \if@endfor
       \@iforgatherrest#3%
     \else
       \@iforloop#3\@@#4{#5}%
     \fi
   \fi
 \fi
\fi
}
%    \end{macrocode}
%\end{macro}
%\changes{1.02}{2007 August 16}{Added \cs{@xfor@storenext}}%
%\begin{macro}{\@xfor@storenext}
% Stores first argument in \cs{@xfor@nextelement}.
%    \begin{macrocode}
\def\@xfor@storenext#1,#2\@@{%
\def\@xfor@nextelement{#1}%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@forgatherrest}
% Get remainder of list (stores in \cs{@forremainder}):
%\changes{1.01}{2007 July 11}{made long}%
%    \begin{macrocode}
\long\def\@forgatherrest#1,\@nil,\@nil{\def\@forremainder{#1}}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@iforgatherrest}
% As above, but there may not be anything before \cs{@nil}:
%\changes{1.01}{2007 July 11}{made long}%
%    \begin{macrocode}
\long\def\@iforgatherrest#1\@nil,\@nil{%
\def\@fortmp{#1}%
\ifx\@fortmp\@empty
 \def\@forremainder{}%
\else
 \@forgatherrest#1\@nil,\@nil
\fi
}
%    \end{macrocode}
%\end{macro}
% Redefine \cs{@iforloop} to check \cs{if@endfor}:
%\begin{macro}{\@iforloop}
%    \begin{macrocode}
\long\def\@iforloop#1,#2\@@#3#4{%
\def#3{#1}%
\ifx#3\@nnil
 \let\@ifornext\@fornoop
\else
 \@xfor@storenext#2,\@nil\@@%
 #4\relax
 \if@endfor
  \@iforgatherrest#2\relax
  \let\@ifornext\@fornoop
 \else
  \let\@ifornext\@iforloop
 \fi
\fi
\@ifornext#2\@@#3{#4}%
}
%    \end{macrocode}
%\end{macro}
%\iffalse
%    \begin{macrocode}
%</xfor.sty>
%    \end{macrocode}
%\fi
%\Finale
\endinput
