diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/generic/eijkhout/repeat.tex |
Initial commit
Diffstat (limited to 'macros/generic/eijkhout/repeat.tex')
-rw-r--r-- | macros/generic/eijkhout/repeat.tex | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/macros/generic/eijkhout/repeat.tex b/macros/generic/eijkhout/repeat.tex new file mode 100644 index 0000000000..0bbb0785f6 --- /dev/null +++ b/macros/generic/eijkhout/repeat.tex @@ -0,0 +1,212 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Repeat loop macro, version 0.93a, September 2006 +% Copyright Victor Eijkhout 1999-2006 +% file name: repeat.tex +% +% Author: +% Victor Eijkhout +% Texas Advanced Computing Center +% The University of Texas at Austin, Austin TX 78758, USA +% +% victor@eijkhout.net +% +% This program is released under the LaTeX Project Public License +% see <http://www.latex-project.org/lppl/> for further information. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% General loop macro: +% \repeat +% \for{<var>} \from{<start>} \by{<step>} \to{<end>} \downto{<end>} +% \until{<cond>} \while{<cond>} +% \do { <loop body> } +% where all control sequences in between \repeat and \do are optional. +% +% var: characters to form a control sequence; +% after \for{index} you can access the loop counter as \index. +% This is a count register; to print it use \number\index. +% start,step,end: integers with obvious relations to the loop counter; +% start and step have a default value of 1 +% cond: (sequence of commands ending in) any TeX \if... test. +% +% Count down instead of up with \downto; the increment given in \by +% is always positive, and is added or subtracted accordingly. +% +% Tests: \until is evaluated at the end of the loop body; \while +% at the beginning of the loop body. +% +% Exit from middle of loop: \breakrepeat +% use this at any place in the loop; in case of a conditional use +% \ifsomething ... \expandafter \breakrepeat \fi +% +% There are some examples at the end of this file, after the \endinput line; +% remove the \endinput statement to see the examples executed. +% Note that the line ends do not cause spaces in the output. +% +% Technical details: +% The loop body is not executed in a group: the braces are those +% of a token list. +% The `for' variable is \let to a \count register. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% revision history: +% 0.9 first release, January 1999 +% 0.91 documentation update, +% csarg-like control sequences made REP... +% counter update made global in case the body issues grouping, +% copyright notice, February 1999 +% 0.92 installed trace switches +% 0.93 spaces are now ignored after each argument group. Author info updated. +% 0.93a removed \bye from \endinput line. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% + +%% +%% Prevent multiple loading of this file +%% +\expandafter\ifx\csname REPdepth\endcsname\relax + \message{Loading loop macro, version 0.93a}% +\else \endinput \fi + +%% +%% Auxiliary stuff +%% +\def\REPcsarg#1#2{\expandafter#1\csname#2\endcsname} +\def\REPcsrom#1{\csname #1\romannumeral\REPdepth\endcsname} +\def\REPcsargrom#1#2{\expandafter#1\csname#2\romannumeral\REPdepth\endcsname} + +\newcount\REPdepth +\let\endrepeat\relax \def\csprotect{} +% Trace switches may later be defined by PAC_utils +\let\REPtraceinit\relax \let\REPtraceexit\relax + +%% +%% Main repeat macro +%% - go to next level and allocate unique counter/toks if this is the +%% first time we visit this level +%% - setup: gather bounds and termination conditions +%% - scoop up body in token list; after the assignment define and +%% execute body +%% +\def\repeat#1\do{\REPtraceinit % exit in \breakrepeat + \advance\REPdepth by 1\relax + \REPcsargrom\ifx{REPcount}\relax + \REPcsargrom{\csname newcount\expandafter\endcsname}{REPcount}% + \REPcsargrom{\csname newtoks\expandafter\endcsname}{REPtoks}% + \REPcsargrom{\csname newtoks\expandafter\endcsname}{REPwtest}% + \REPcsargrom{\csname newtoks\expandafter\endcsname}{REPutest}% + \fi \REPzero \def\REPsign{}\def\REPcomp{>}\REPsetup{#1}% + \edef\REPtmp + {\def\REPcsargrom\noexpand{REPrepeat}{\REPcsargrom\noexpand{REPbody}}}\REPtmp + \afterassignment\REPdxbody\REPcsrom{REPtoks}} +%% +%% Define and execute loop body +%% This is done with an \edef to construct the actual sequence +%% +\def\REPdxbody{\REPcsargrom\edef{REPbody}{% + \REPcsargrom\the{REPwtest}% + \noexpand\the\REPcsargrom\noexpand{REPtoks}% + \REPcsargrom\the{REPutest}% + \global\REPcsargrom\advance{REPcount} by \REPsign\REPcsrom{REPinc}\relax + \noexpand\endrepeat + \REPcsargrom\noexpand{REPrepeat}}% + \REPcsrom{REPbody}\ignorespaces} +%% +%% Stop test +%% In order to stop, issue a +%% \breakrepeat which scoops up the rest of the body and exits +%% +\def\breakrepeat#1\endrepeat{\REPzero\REPcsargrom\let{REPrepeat}\relax + \advance\REPdepth by -1 \REPtraceexit + } +%% +%% Setup +%% gather bounds and termination conditions +%% +\def\REPsetup#1{% + \begingroup + \def\for##1{% + \edef\REPtmp{% + \global\let\REPcsarg\noexpand{##1}\REPcsrom{REPcount}\ignorespaces}% + \REPtmp}% + \def\from##1{\REPcsargrom\global{REPcount}##1\ignorespaces}% + \def\to##1{% + \edef\REPtmp{\global\REPcsargrom\noexpand{REPwtest}= + {\REPcsargrom\the{REPwtest}% + \noexpand\ifnum\REPcsargrom\noexpand{REPcount}\REPcomp##1\relax + \noexpand\expandafter \noexpand\breakrepeat + \noexpand\fi}\ignorespaces}% + \REPtmp}% + \def\downto##1{% + \gdef\REPsign{-}\gdef\REPcomp{<}\to{##1}\ignorespaces}% + \def\by##1{\ifnum##1<0 \message{REPEAT: increment has to be >0}% + \REPcsargrom\gdef{REPinc}{-##1}\else + \REPcsargrom\gdef{REPinc}{##1}\fi\ignorespaces}% + \def\until##1{% + \edef\REPtmp{\global\REPcsargrom\noexpand{REPutest}= + {\noexpand##1\relax + \noexpand\expandafter \noexpand\breakrepeat \noexpand\fi}\ignorespaces}% + \REPtmp}% + \def\while##1{% + \edef\REPtmp{\global\REPcsargrom\noexpand{REPwtest}= + {\noexpand##1\relax \noexpand\else + \noexpand\expandafter \noexpand\breakrepeat \noexpand\fi}\ignorespaces}% + \REPtmp}% + \from{1}\by{1}#1% + \endgroup} +\def\REPzero + {\REPcsrom{REPtoks}{}\REPcsrom{REPutest}{}\REPcsrom{REPwtest}{}% + \REPcsargrom\def{REPbody}{}} + +\endinput + +%\tracingmacros2 +\newcount\tmpcount % used in some examples below +1 +\repeat \for{i} + \by{2} + \do {% + \ifnum\i=13 \expandafter\breakrepeat \fi + \message{doing \number\i}% +}% +2 +\repeat \for{iii} + \to{8} + \do {} +\message{After loop: \number\iii}% +3 +\repeat \for{i} + \from{10} + \by{2} + \downto{0} + \do {\message{countdown \number\i}} +4 +\repeat \for{x} \while{\ifnum\x<7} + \do {\message{going \number\x}} +5 +\repeat \to{3} \do {\message{hello there!}} +6 +\repeat \for{j} + \until{\tmpcount\j \divide\tmpcount by 37 \noexpand\ifnum\tmpcount=1} + \do {\message{testing \number\j}} +7 +\repeat \for{i} \by{2} \to{10} \do + {\repeat \for{j} \from{\i} \by{3} \to{18} + \do {\message{(\number\i.\number\j)}} + } +8 + +1 +2 +3 +4 +5 +6 +7 +8 + +% infinite loop +%\repeat \do {} + +\bye |