summaryrefslogtreecommitdiff
path: root/fonts/igo/repeat.tex
blob: 7c99f36d35e8f4240059e6bf7a4ccbedbb592e8a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Repeat loop macro, version 0.93, May 2003
% Copyright Victor Eijkhout 2000
% file name: repeat.tex
%
% Author:
% Victor Eijkhout
% Department of Computer Science
% University of Tennessee, Knoxville TN 37996
%
% victor@eijkhout.net
%
% This program is free software; you can redistribute it and/or
% modify it under the terms of the GNU General Public License
% as published by the Free Software Foundation; either version 2
% of the License, or (at your option) any later version.
% 
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% For a copy of the GNU General Public License, write to the 
% Free Software Foundation, Inc.,
% 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA,
% or find it on the net, for instance at
% http://www.gnu.org/copyleft/gpl.html
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% 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.
% The space after each argument is mandatory!
% (This implies that you will have to write "\from\i" as "\from{\i}".)
%
% 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.
%
% 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, eliminated unwanted space caused by
%      "\for{ijk} \do{...}", December 2000
% 0.93 added missing percent signs at end of lines to prevent unwanted
%      spaces, May 2003 ({\'E}. Dupuis).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%

%%
%% Prevent multiple loading of this file
%%
\expandafter\ifx\csname REPdepth\endcsname\relax
  \message{Loading loop macro, version 0.93}%
\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}
%\def\cscsarg#1#2#3{\expandafter#1\expandafter#2\csname#3\endcsname}
%\def\REPcsREPcsargrom#1#2#3{\expandafter#1\expandafter#2%
%                      \csname#3\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}}%
%%
%% 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}}\REPtmp}%
    \def\from##1 {\REPcsargrom\global{REPcount}##1\relax}%
    \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}}\REPtmp}%
    \def\downto##1 {\gdef\REPsign{-}\gdef\REPcomp{<}\to{##1}}%
    \def\by##1 {\ifnum##1<0 \message{REPEAT: increment has to be >0}%
               \REPcsargrom\gdef{REPinc}{-##1}\else%
               \REPcsargrom\gdef{REPinc}{##1}\fi}%
    \def\until##1 {\edef\REPtmp{\global\REPcsargrom\noexpand{REPutest}=%
       {\noexpand##1\relax%
        \noexpand\expandafter \noexpand\breakrepeat \noexpand\fi}}\REPtmp}%
    \def\while##1 {\edef\REPtmp{\global\REPcsargrom\noexpand{REPwtest}=%
       {\noexpand##1\relax \noexpand\else%
        \noexpand\expandafter \noexpand\breakrepeat \noexpand\fi}}\REPtmp}%
    \from{1} \by{1} #1%
  \endgroup}%
\def\REPzero%
   {\REPcsrom{REPtoks}{}\REPcsrom{REPutest}{}\REPcsrom{REPwtest}{}%
    \REPcsargrom\def{REPbody}{}}%

\endinput

%\tracingmacros2
\repeat \for{i} \by{2} \do {
  \ifnum\i=13 \expandafter\breakrepeat \fi
  \message{doing \number\i}
}

\repeat \for{iii} \to{8} \do {}
\message{After loop: \number\iii}

\repeat \for{i} \from{10} \by{2} \downto{0} \do {
  \message{countdown \number\i}
}

\repeat \for{x} \while{\ifnum\x<7} \do {
  \message{going \number\x}
}

\repeat \to{3} \do {
  \message{hello there!}
}

\newcount\tmpcount
\repeat \for{j}
        \until{\tmpcount\j \divide\tmpcount by 37 \noexpand\ifnum\tmpcount=1}
  \do {
    \message{testing \number\j}
}

\repeat \for{i} \by{2} \to{10} \do
 {\repeat \for{j} \from{\i} \by{3} \to{18} \do
  {\message{(\number\i.\number\j)}
 }}

% infinite loop
%\repeat \do {}

\bye