syst-ext.mkii / last modification: 2020-01-30 14:15
%D \module
%D   [       file=syst-ext,
%D        version=1995.10.10,
%D          title=\CONTEXT\ System Macros,
%D       subtitle=Extras,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

\writestatus{loading}{ConTeXt System Macros / Extras}

%D In this second system module, we continue the definition of
%D some handy commands.

\unprotect

%D \macros
%D   {rawgetparameters}
%D
%D A raw and dirty alternative for \type {\getparameters}; no
%D checking is done!

% \def\rawgetparameters[#1][#2]% scheelt 5\%
%   {\def\rawparameterprefix{#1}%
%    \expandafter\rawsetparameter#2,]=,}

\def\rawsetparameter#1=#2,%
  {\if]#1\else
     \expandafter\def\csname\rawparameterprefix#1\endcsname{#2}%
     \expandafter\rawsetparameter
   \fi}

% the next one handles empty #1 okay:

\def\rawgetparameters[#1][#2% some 5-10% faster
  {\ifx#2]% test is needed, else bomb on [#1][]
     \expandafter\gobbleoneargument
   \else
     \def\rawparameterprefix{#1}%
     \expandafter\dorawgetparameters
   \fi#2}

\def\dorawgetparameters#1]%
  {\expandafter\rawsetparameter#1,]=,}

%D \macros
%D   {doglobal,
%D    redoglobal,dodoglobal,resetglobal}
%D
%D The two macros \type {\redoglobal} and \type{\dodoglobal} are
%D used in this and some other modules to enforce a user
%D specified \type {\doglobal} action. The last and often only
%D global assignment in a macro is done with
%D \type {\dodoglobal}, but all preceding ones with
%D \type {\redoglobal}. When using only alternatives, one can
%D reset this mechanism with \type {\resetglobal}.

\def\doglobal
  {\let\redoglobal\global
   \def\dodoglobal{\resetglobal\global}}

\def\resetglobal
  {\let\redoglobal\relax
   \let\dodoglobal\relax}

\resetglobal

%D New:

\def\doglobal
  {\ifx\redoglobal\relax
     \let\redoglobal\global
     \let\dodoglobal\@@dodoglobal
  %\else
  %  \writestatus{system}{global not reset, warn me!}%
   \fi}

\def\@@dodoglobal
  {\resetglobal\global}

\def\saveglobal
  {\let\@@dodoglobal\dodoglobal
   \let\@@redoglobal\redoglobal}

\def\restoreglobal
  {\let\redoglobal\@@redoglobal
   \let\dodoglobal\@@dodoglobal}

%D A very useful application of this macro is \type {\newif},
%D \TEX's fake boolean type. Not being a primitive,
%D \type {\global} hopelessly fails here. But a slight
%D adaption of Knuth's original macro permits:
%D
%D \starttyping
%D \doglobal\newif\iftest
%D \stoptyping
%D
%D Of course one can still say:
%D
%D \starttyping
%D \global\testtrue
%D \global\testfalse
%D \stoptyping
%D
%D Apart from the prefixes, a few more \type{\expandafters}
%D are needed:

\def\newif#1%
  {\scratchcounter\escapechar
   \escapechar\minusone
   \expandafter\expandafter\expandafter
     \redoglobal\expandafter\expandafter\expandafter
       \edef\@if#1{true}{\let\noexpand#1\noexpand\iftrue}%
   \expandafter\expandafter\expandafter
     \redoglobal\expandafter\expandafter\expandafter
       \edef\@if#1{false}{\let\noexpand#1\noexpand\iffalse}%
   \dodoglobal\@if#1{false}%
   \escapechar\scratchcounter}

%D Also:

\def\define#1%
  {\ifx#1\undefined
     \expandafter\long\expandafter\def
   \else
     \message{[\noexpand#1is already defined]}%
     \expandafter\long\expandafter\def\expandafter\gobbleddefinition
   \fi#1}

\def\redefine#1%
  {\ifx#1\undefined\else
     \message{[\noexpand#1is redefined]}%
   \fi
   \long\def#1}

% \define\hans{hans}
% \redefine\hans{hans}
% \define\hans#1[]#2#3{hans}

%D The next variant fits nicely in the setups syntax:
%D
%D \starttyping
%D \starttexdefinition bagger [#1] #2
%D     oeps
%D     #1
%D     oeps
%D \stoptexdefinition
%D
%D \bagger [a] {b}
%D \stoptyping

\bgroup \obeylines

\gdef\starttexdefinition%
  {\bgroup%
   \obeylines%
   \dostarttexdefinition}

\gdef\dostarttexdefinition #1
  {\catcode13=\@@ignore%
   \doifinstringelse\letterhash{\detokenize{#1}}\dodostarttexdefinition\nonostarttexdefinition#1
  }

\long\gdef\dodostarttexdefinition#1 #2
  {\dododostarttexdefinition{#1}{#2}}

\long\gdef\dododostarttexdefinition#1#2#3\stoptexdefinition%
  {\egroup%
   \long\setvalue{#1}#2{#3}}

\long\gdef\nonostarttexdefinition#1
  {\nononostarttexdefinition{#1}{}}

\long\gdef\nononostarttexdefinition#1#2#3\stoptexdefinition%
  {\egroup%
   \long\setvalue{#1}{#3}}

\egroup

%D \macros
%D   {newcounter,
%D    increment,decrement}
%D
%D Unfortunately the number of \COUNTERS\ in \TEX\ is limited,
%D but fortunately we can store numbers in a macro. We can
%D increment such pseudo \COUNTERS\ with \type{\increment}.
%D
%D \starttyping
%D \increment(\counter,20)
%D \increment(\counter,-4)
%D \increment(\counter)
%D \increment\counter
%D \stoptyping
%D
%D After this sequence of commands, the value of
%D \type{\counter} is 20, 16, 17 and~18. Of course there is
%D also the complementary command \type{\decrement}.
%D
%D Global assignments are possible too, using \type{\doglobal}:
%D
%D \starttyping
%D \doglobal\increment\counter
%D \stoptyping
%D
%D When \type{\counter} is undefined, it's value is initialized
%D at~0. It is nevertheless better to define a \COUNTER\
%D explicitly. One reason could be that the \COUNTER\ can be
%D part of a test with \type{\ifnum} and this conditional does
%D not accept undefined macro's. The \COUNTER\ in our example
%D can for instance be defined with:
%D
%D \starttyping
%D \newcounter\counter
%D \stoptyping
%D
%D The command \type{\newcounter} must not be confused with
%D \type{\newcount}! Of course this mechanism is much slower
%D than using \TEX's \COUNTERS\ directly. In practice
%D \COUNTERS\ (and therefore our pseudo counters too) are
%D seldom the bottleneck in the processing of a text. Apart
%D from some other incompatilities we want to mention a pitfal
%D when using \type{\ifnum}.
%D
%D \starttyping
%D \ifnum\normalcounter=\pseudocounter \doif \else \doelse \fi
%D \ifnum\pseudocounter=\normalcounter \doif \else \doelse \fi
%D \stoptyping
%D
%D In the first test, \TEX\ continues it's search for the
%D second number after reading  \type{\pseudocounter}, while
%D in the second test, it stops reading after having
%D encountered a real one. Tests like the first one therefore
%D can give unexpected results, for instance execution
%D of \type{\doif} even if both numbers are unequal.

\def\zerocountervalue{0}

\def\newcounter#1%
  {\dodoglobal\let#1\zerocountervalue}

% This is the original implementation:
%
% \def\dodododoincrement(#1,#2)%
%   {\ifx#1\undefined
%      \redoglobal\let#1\zerocountervalue
%    \else\ifx#1\relax % \csname...\endcsname
%      \redoglobal\let#1\zerocountervalue
%    \fi\fi
%    \scratchcounter=#2\relax
%    \scratchcounter=\incrementsign\scratchcounter
%    \advance\scratchcounter #1\relax
%    \dodoglobal\edef#1{\the\scratchcounter}}
%
% \def\dododoincrement#1%
%   {\dodododoincrement(#1,1)}
%
% \def\dodoincrement(#1%
%   {\doifnextcharelse,%
%      {\dodododoincrement(#1}{\dodododoincrement(#1,1}}
%
% \def\doincrement#1%
%   {\def\incrementsign{#1}%
%    \doifnextcharelse(\dodoincrement\dododoincrement}
%
% \def\increment{\doincrement+}
% \def\decrement{\doincrement-}
%
% And this is the one optimized for speed:

% maxcounter = 2\maxdimen=1

\def\!!zerocount {0} % alongside \zerocount
\def\!!minusone {-1} % alongside \minusone
\def\!!plusone   {1} % alongside \plusone

\beginTEX

\def\dodoindecrement#1(#2,#3)%
  {\ifx#2\undefined
     \redoglobal\let#2\zerocountervalue
   \else\ifx#2\relax % \csname...\endcsname
     \redoglobal\let#2\zerocountervalue
   \fi\fi
   \scratchcounter#3\relax
   \scratchcounter#1\scratchcounter
   \advance\scratchcounter#2\relax
   \dodoglobal\edef#2{\the\scratchcounter}}

\def\dodoincrement(#1%
  {\doifnextcharelse,{\dodoindecrement+(#1}{\dodoindecrement+(#1,1}}

\def\dododecrement(#1%
  {\doifnextcharelse,{\dodoindecrement-(#1}{\dodoindecrement-(#1,1}}

\def\doincrement#1% 10% faster alternative
  {\ifx#1\undefined
     \dodoglobal\let#1\!!plusone
   \else\ifx#1\relax % \csname...\endcsname
     \dodoglobal\let#1\!!plusone
   \else
     \fastincrement#1%
   \fi\fi}

\def\dodecrement#1% 10% faster alternative
  {\ifx#1\undefined
     \dodoglobal\let#1\!!minusone
   \else\ifx#1\relax % \csname...\endcsname
     \dodoglobal\let#1\!!minusone
   \else
     \fastdecrement#1%
   \fi\fi}

\def\fastdecrement#1% 50% faster alternative
  {\scratchcounter#1\advance\scratchcounter\minusone
   \dodoglobal\edef#1{\the\scratchcounter}}

\def\fastincrement#1% 50% faster alternative
  {\scratchcounter#1\advance\scratchcounter\plusone
   \dodoglobal\edef#1{\the\scratchcounter}}

\endTEX

\beginETEX \numexpr

% \def\doindecrement#1#2%
%   {\dodoglobal\edef#2%
%      {\the\numexpr(\ifx#2\undefined\else\ifx#2\relax\else#2\fi\fi#11)}}
%
% \def\doincrement{\doindecrement+}
% \def\dodecrement{\doindecrement-}
%
% some 3\% faster:

\def\doindecrement#1#2%
  {\dodoglobal\edef#2%
     {\the\numexpr\ifx#2\undefined\else\ifx#2\relax\else#2\fi\fi+#1\relax}}

\def\doincrement{\doindecrement\plusone }
\def\dodecrement{\doindecrement\minusone}

\def\dodoindecrement#1#2,#3)%
  {\dodoglobal\edef#2%
     {\the\numexpr\ifx#2\undefined\else\ifx#2\relax\else#2\fi\fi#1#3\relax}}

\def\dodoincrement(#1%
  {\doifnextcharelse,{\dodoindecrement+#1}{\dodoindecrement+#1,\plusone}}

\def\dododecrement(#1%
  {\doifnextcharelse,{\dodoindecrement-#1}{\dodoindecrement-#1,\plusone}}

\def\fastincrement#1{\dodoglobal\edef#1{\the\numexpr#1+\plusone \relax}}
\def\fastdecrement#1{\dodoglobal\edef#1{\the\numexpr#1+\minusone\relax}}

\endETEX

\def\increment{\doifnextcharelse(\dodoincrement\doincrement}
\def\decrement{\doifnextcharelse(\dododecrement\dodecrement}

\def\incrementvalue#1{\expandafter\increment\csname#1\endcsname}
\def\decrementvalue#1{\expandafter\decrement\csname#1\endcsname}

%D \macros
%D  {newsignal}
%D
%D When writing advanced macros, we cannot do without
%D signaling. A signal is a small (invisible) kern or penalty
%D that signals the next macro that something just happened.
%D This macro can take any action depending on the previous
%D signal. Signals must be unique and the next macro takes care
%D of that.
%D
%D \starttyping
%D \newsignal\somesignal
%D \stoptyping
%D
%D Signals old dimensions and can be used in skips, kerns and
%D tests like \type{\ifdim}.

\newdimen\maximumsignal % step is about 0.00025pt

\def\newsignal#1%
  {\ifx#1\undefined
     \advance\maximumsignal 2sp % to be save in rounding
     \edef#1{\the\maximumsignal}%
   \fi}

%D \macros
%D   {newskimen}
%D
%D \TEX\ offers 256 \DIMENSIONS\ and \SKIPS. Unfortunately this
%D amount is too small to suit certain packages. Therefore when
%D possible one should use:
%D
%D \starttyping
%D \newskimen\tempskimen
%D \stoptyping
%D
%D This commands allocates a \DIMENSION\ or a \SKIP, depending
%D on the availability. One should be aware of the difference
%D between both. When searching for some glue \TEX\ goes on
%D searching till it's sure that no other glue component if
%D found. This search can be canceled by using \type{\relax}
%D when possible and needed.
%D
%D \starttyping
%D \def\newskimen#1%
%D   {\ifx#1\undefined
%D      \ifnum\count11>\count12
%D        \newskip#1\relax
%D      \else
%D        \newdimen#1\relax
%D      \fi
%D    \fi}
%D \stoptyping
%D
%D In order to make this macro work in plain \TEX\ too, we
%D use the following alternative, which fools \TEX\ about
%D the new commands being \type {\outer} ones.

% \def\newskimen#1%
%   {\ifx#1\undefined
%      \csname new\ifnum\count11>\count12 skip\else dimen\fi\endcsname#1%
%    \fi}

\let\newskimen\newdimen % it's all etex or later now

%D \macros
%D   {strippedcsname}
%D
%D The next macro can be very useful when using \type{\csname}
%D like in:
%D
%D \starttyping
%D \csname if\strippedcsname\something\endcsname
%D \stoptyping
%D
%D This expands to \type{\ifsomething}.
%D
%D \starttyping
%D \def\strippedcsname
%D   {\expandafter\gobbleoneargument\string}
%D \stoptyping
%D
%D Slower but better:

\ifx\letterbackslash\undefined
  {\catcode`.=0 .catcode`.\ 12 .xdef.letterbackslash{.string\}} % hack
\fi

\def\strippedcsname#1% this permits \strippedcsname{\xxx} and \strippedcsname{xxx}
  {\expandafter\dostrippedcsname\string#1}

\def\dostrippedcsname#1%
  {\if\noexpand#1\letterbackslash\else#1\fi}

%D \macros
%D   {savenormalmeaning}
%D
%D We will use this one in:

\def\savenormalmeaning#1%
  {\ifundefined{normal\strippedcsname#1}%
     \letvalue{normal\strippedcsname#1}#1%
   \fi}

%D \macros
%D   {newconditional,
%D    settrue, setfalse,
%D    ifconditional,then}
%D
%D \TEX's lacks boolean variables, although the \PLAIN\ format
%D implements \type{\newif}. The main disadvantage of this
%D scheme is that it takes three hash table entries. A more
%D memory saving alternative is presented here. A conditional
%D is defined by:
%D
%D \starttyping
%D \newconditional\doublesided
%D \setfalse
%D \stoptyping
%D Setting a conditional is done by \type{\settrue} and
%D \type{\setfalse}:
%D
%D \starttyping
%D \settrue\doublesided
%D \setfalse
%D \stoptyping
%D while testing is accomplished by:
%D
%D \starttyping
%D \ifconditional\doublesided  ... \else ... \fi
%D \setfalse
%D \stoptyping
%D We cannot use the simple scheme:
%D
%D \starttyping
%D \def\settrue #1{\let#1=\iftrue}
%D \def\setfalse#1{\let#1=\iffalse}
%D \stoptyping
%D
%D Such an implementation gives problems with nested
%D conditionals. The next implementation is abaou as fast
%D and just as straightforward:

\def\settrue #1{\chardef#1\zerocount}
\def\setfalse#1{\chardef#1\plusone}

\let\newconditional = \setfalse
\let\ifconditional  = \ifcase

\let\then\relax % so that we can say \ifnum1>2\then -)

%D \macros
%D   {ifzeropt}
%D
%D The next macro is both cosmetic and byte saving. It is
%D pretty \type{\if}||safe too. It can be used in cases
%D like:
%D
%D \starttyping
%D \ifzeropt \somedimen ... \else ... \fi
%D \stoptyping

\let\ifzeropt\ifcase

%D \macros
%D   {dorecurse,recurselevel,recursedepth,
%D    dostepwiserecurse,
%D    for}
%D
%D \TEX\ does not offer us powerfull for||loop mechanisms. On
%D the other hand its recursion engine is quite unique. We
%D therefore identify the for||looping macros by this method.
%D The most simple alternative is the one that only needs a
%D number.
%D
%D \starttyping
%D \dorecurse {n} {whatever we want}
%D \stoptyping
%D
%D This macro can be nested without problems and therefore be
%D used in situations where \PLAIN\ \TEX's \type{\loop} macro
%D ungracefully fails. The current value of the counter is
%D available in \type{\recurselevel}, before as well as after
%D the \typ{whatever we wat} stuff.
%D
%D \starttyping
%D \dorecurse               % inner loop
%D   {10}
%D   {\recurselevel:          % outer value
%D      \dorecurse          % inner loop
%D        {\recurselevel}     % outer value
%D        {\recurselevel}     % inner value
%D      \dorecurse          % inner loop
%D        {\recurselevel}     % outer value
%D        {\recurselevel}     % inner value
%D    \endgraf}
%D \stoptyping
%D
%D In this example the first, second and fourth
%D \type{\recurselevel} concern the outer loop, while the third
%D and fifth one concern the inner loop. The depth of the
%D nesting is available for inspection in \type{\recursedepth}.
%D
%D Both \type{\recurselevel} and \type{\recursedepth} are
%D macros. The real \COUNTERS\ are hidden from the user because
%D we don't want any interference.

\newcount\outerrecurse
\newcount\innerrecurse

\def\recursedepth{\the\outerrecurse}
\def\recurselevel{0}

\let\nextrecurse\relax

%D Acceptable:
%D
%D \starttyping
%D \long\def\dostepwiserecurse#1#2#3%
%D   {\let\nextrecurse\gobblefourarguments
%D    \ifnum#3>0\relax\ifnum#2<#1\relax\else
%D      \def\nextrecurse{\dosetstepwiserecurse>}%
%D    \fi\fi
%D    \ifnum#3<0\relax\ifnum#1<#2\relax\else
%D      \def\nextrecurse{\dosetstepwiserecurse<}%
%D    \fi\fi
%D    \nextrecurse{#1}{#2}{#3}}
%D \stoptyping
%D
%D Better:
%D
%D \starttyping
%D \long\def\dostepwiserecurse#1#2#3%
%D   {\let\nextrecurse\gobblefourarguments
%D    \ifnum#3>0\relax \ifnum#2<#1\relax \else
%D      \def\nextrecurse{\dosetstepwiserecurse>}%
%D    \fi \else \ifnum#3<0\relax \ifnum#1<#2\relax \else
%D      \def\nextrecurse{\dosetstepwiserecurse<}%
%D    \fi \fi \fi
%D    \nextrecurse{#1}{#2}{#3}}
%D
%D \def\@@irecurse{@@irecurse}  % stepper
%D \def\@@nrecurse{@@nrecurse}  % number of steps
%D \def\@@srecurse{@@srecurse}  % step
%D \def\@@drecurse{@@drecurse}  % direction, < or >
%D \def\@@arecurse{@@arecurse}  % action
%D
%D \long\def\dosetstepwiserecurse#1#2#3#4#5%
%D   {\global\advance\outerrecurse 1
%D    \setevalue{\@@drecurse\recursedepth}{#1}%
%D    \setevalue{\@@irecurse\recursedepth}{\number#2}%
%D    \setevalue{\@@nrecurse\recursedepth}{\number#3}%
%D    \setevalue{\@@srecurse\recursedepth}{\number#4}%
%D    \long\setvalue{\@@arecurse\recursedepth}{#5}%
%D    \dodorecurse}
%D
%D \def\donorecurse
%D   {}
%D
%D \def\dododorecurse
%D   {\edef\recurselevel{\csname\@@irecurse\recursedepth\endcsname}%
%D    \getvalue{\@@arecurse\recursedepth}%
%D    \edef\recurselevel{\csname\@@irecurse\recursedepth\endcsname}%
%D    \innerrecurse\recurselevel
%D    \advance\innerrecurse \csname\@@srecurse\recursedepth\endcsname
%D    \setevalue{\@@irecurse\recursedepth}{\the\innerrecurse}%
%D    \dodorecurse}
%D
%D \def\dodorecurse
%D   {\ifnum\csname\@@irecurse\recursedepth\endcsname
%D          \csname\@@drecurse\recursedepth\endcsname
%D          \csname\@@nrecurse\recursedepth\endcsname\relax
%D      \expandafter\nododorecurse
%D    \else
%D      \expandafter\dododorecurse
%D    \fi}
%D
%D \def\nododorecurse
%D   {\global\advance\outerrecurse -1
%D    \edef\recurselevel{\csname\@@irecurse\recursedepth\endcsname}}
%D \stoptyping
%D
%D Cleaner and much faster:

\def\@@irecurse{@@ir@@} % ecurse} % stepper
\def\@@arecurse{@@ar@@} % ecurse} % action

% \mathchardef

\long\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
  {\global\advance\outerrecurse \plusone
   \long\global\@EA\def\csname\@@arecurse\recursedepth\endcsname{#4}%
   \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
   \ifnum#3>0\relax
     \ifnum#2<#1\relax
       \let\nextrecurse\exitstepwiserecurse
     \else
       \let\nextrecurse\dodostepwiserecurse
     \fi
   \else
     \ifnum#3<0\relax
       \ifnum#1<#2\relax
         \let\nextrecurse\exitstepwiserecurse
       \else
         \let\nextrecurse\dodostepwisereverse
       \fi
     \else
       \let\nextrecurse\exitstepwiserecurse
     \fi
   \fi\expanded{\nextrecurse{\number#1}{\number#2}{\number#3}}}

\beginETEX \numexpr

\long\def\dodostepwiserecurse#1#2#3% from to step
  {\ifnum#1>#2\relax
     \@EA\nodostepwiserecurse
   \else
     \def\recurselevel{#1}%
     \@EAEAEA\redostepwiserecurse\@EA
   \fi\@EA{\the\numexpr\recurselevel+#3\relax}{#2}{#3}}

\endETEX

\beginTEX

\long\def\dodostepwiserecurse#1#2#3% from to step
  {\ifnum#1>#2\relax
     \@EA\nodostepwiserecurse
   \else
     \def\recurselevel{#1}%
     \innerrecurse#1\advance\innerrecurse#3\relax
     \@EAEAEA\redostepwiserecurse\@EA
   \fi\@EA{\the\innerrecurse}{#2}{#3}}

\endTEX

\def\expandrecursecontent
  {\csname\@@arecurse\recursedepth\endcsname}

\def\redostepwiserecurse
  {\expandrecursecontent\dodostepwiserecurse}

\beginETEX \numexpr

\long\def\dodostepwisereverse#1#2#3% from to step
  {\ifnum#1<#2\relax
     \@EA\nodostepwiserecurse
   \else
     \def\recurselevel{#1}%
     \@EAEAEA\redostepwisereverse\@EA
   \fi\@EA{\the\numexpr\recurselevel#3\relax}{#2}{#3}}

\endETEX

\beginTEX

\long\def\dodostepwisereverse#1#2#3% from to step
  {\ifnum#1<#2\relax
     \@EA\nodostepwiserecurse
   \else
     \def\recurselevel{#1}%
     \innerrecurse#1\relax
     \advance\innerrecurse#3\relax
     \@EAEAEA\redostepwisereverse\@EA
   \fi\@EA{\the\innerrecurse}{#2}{#3}}

\endTEX

\def\redostepwisereverse
  {\expandrecursecontent\dodostepwisereverse}

\def\exitstepwiserecurse
  {\nodostepwiserecurse\relax}

\def\nodostepwiserecurse#1#2#3#4%
  {\@EA\let\@EA\recurselevel\csname\@@irecurse\recursedepth\endcsname
   \global\advance\outerrecurse \minusone}

\def\nonostepwiserecurse#1#2#3%
  {\@EA\let\@EA\recurselevel\csname\@@irecurse\recursedepth\endcsname
   \global\advance\outerrecurse \minusone}

\def\dorecurse#1%
  {\dostepwiserecurse1{#1}1}

%D As we can see here, the simple command \type{\dorecurse} is
%D a special case of the more general:
%D
%D \starttyping
%D \dostepwiserecurse {from} {to} {step} {action}
%D \stoptyping
%D
%D This commands accepts positive and negative steps. Illegal
%D values are handles as good as possible and the macro accepts
%D numbers and \COUNTERS.
%D
%D \starttyping
%D \dostepwiserecurse  {1} {10}  {2} {...}
%D \dostepwiserecurse {10}  {1} {-2} {...}
%D \stoptyping
%D
%D Because the simple case is used often, we implement it
%D more efficiently:

\long\def\dorecurse#1%
  {\ifcase#1\relax
     \expandafter\gobbletwoarguments
   \or
     \expandafter\ydorecurse
   \else
     \expandafter\xdorecurse
   \fi{#1}}

\long\def\xdorecurse#1#2%
  {\global\advance\outerrecurse \plusone
   \long\global\@EA\def\csname\@@arecurse\recursedepth\endcsname{#2}%
   \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
   \@EA\dodorecurse\@EA1\@EA{\number#1}}

\long\def\ydorecurse#1#2%
  {\global\advance\outerrecurse \plusone
   \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
   \let\recurselevel\!!plusone
   #2%
   \@EA\let\@EA\recurselevel\csname\@@irecurse\recursedepth\endcsname
   \global\advance\outerrecurse \minusone}

\beginETEX \numexpr

\long\def\dodorecurse#1#2% from to
  {\ifnum#1>#2\relax
     \@EA\nodorecurse
   \else
     \def\recurselevel{#1}%
     \@EAEAEA\redorecurse
   \fi\@EA{\the\numexpr\recurselevel+\plusone\relax}{#2}}

\endETEX

\beginTEX

\long\def\dodorecurse#1#2% from to
  {\ifnum#1>#2\relax
     \@EA\nodorecurse
   \else
     \def\recurselevel{#1}%
     \innerrecurse#1\advance\innerrecurse\plusone
     \@EAEAEA\redorecurse
   \fi\@EA{\the\innerrecurse}{#2}}

\endTEX

\def\redorecurse
  {\expandrecursecontent\dodorecurse}

\def\nodorecurse#1#2#3%
  {\@EA\let\@EA\recurselevel\csname\@@irecurse\recursedepth\endcsname
   \global\advance\outerrecurse \minusone }

%D \macros
%D   {doloop,exitloop}
%D
%D Sometimes loops are not determined by counters, but by
%D (a combinations of) conditions. We therefore implement a
%D straightforward loop, which can only be left when we
%D explictly exit it. Nesting is supported. First we present
%D a more extensive alternative.
%D
%D \starttyping
%D \doloop
%D   {Some kind of typesetting punishment \par
%D    \ifnum\pageno>100 \exitloop \fi}
%D \stoptyping
%D
%D When needed, one can call for \type{\looplevel} and
%D \type{\loopdepth}.
%D
%D If we write this macros from scratch, we end up with
%D something like the ones described above:
%D
%D \starttyping
%D \def\@@eloop{@@eloop}  % exit
%D \def\@@iloop{@@iloop}  % stepper
%D \def\@@aloop{@@aloop}  % action
%D
%D \newcount\outerloop
%D
%D \def\loopdepth%
%D   {\the\outerloop}
%D
%D \def\exitloop%
%D   {\setevalue{\@@eloop\loopdepth}{0}}
%D
%D \long\def\doloop#1%
%D   {\global\advance\outerloop by 1
%D    \setevalue{\@@iloop\loopdepth}{1}%
%D    \setevalue{\@@eloop\loopdepth}{1}%
%D    \long\setvalue{\@@aloop\loopdepth}{#1}%
%D    \dodoloop}
%D
%D \def\dodonoloop%
%D   {\global\advance\outerloop by -1\relax}
%D
%D \def\dododoloop%
%D   {\edef\looplevel{\getvalue{\@@iloop\loopdepth}}%
%D    \innerrecurse=\looplevel
%D    \advance\innerrecurse by 1
%D    \setevalue{\@@iloop\loopdepth}{\the\innerrecurse}%
%D    \getvalue{\@@aloop\loopdepth}%
%D    \edef\looplevel{\getvalue{\@@iloop\loopdepth}}%
%D    \dodoloop}
%D
%D \def\dodoloop%
%D   {\ifnum\getvalue{\@@eloop\loopdepth}=0
%D      \expandafter\dodonoloop
%D    \else
%D      \expandafter\dododoloop
%D    \fi}
%D
%D \def\doloop%
%D   {\dostepwiserecurse{1}{\maxdimen}{1}}
%D
%D \def\exitloop
%D   {\setvalue{\@@irecurse\recursedepth}{\maxdimen}}
%D
%D \def\looplevel{\recurselevel}
%D \def\loopdepth{\recursedepth}
%D \stoptyping
%D
%D We don't have to declare new counters for \type{\looplevel}
%D and \type{\loopdepth} because we can use \type{\recurselevel}
%D and \type{\recursedepth}.
%D
%D We prefer however a more byte saving implementation, that
%D executes of course a bit slower.
%D
%D \starttyping
%D \def\doloop%
%D   {\dostepwiserecurse1\maxdimen1}
%D
%D \def\exitloop%
%D   {\letvalue{\@@irecurse\recursedepth}\maxdimen}
%D \stoptyping
%D
%D Although, the next version is faster because it used the
%D simple loop.

\let\endofloop\donothing

\long\def\doloop#1%
  {\global\advance\outerrecurse \plusone
   \long\global\@EA\def\csname\@@arecurse\recursedepth\endcsname{#1}%
   \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
   \let\endofloop\dodoloop
   \dodoloop1} % no \plusone else \recurselevel wrong

\beginETEX \numexpr

\long\def\dodoloop#1%
  {\def\recurselevel{#1}%
   \@EA\redoloop\@EA{\the\numexpr\recurselevel+\plusone\relax}}

\endETEX

\beginTEX

\long\def\dodoloop#1%
  {\def\recurselevel{#1}%
   \innerrecurse#1\advance\innerrecurse\plusone
   \@EA\redoloop\@EA{\the\innerrecurse}}

\endTEX

\def\redoloop
  {\expandrecursecontent\endofloop}

\def\nodoloop#1%
  {\let\endofloop\dodoloop % new, permits nested \doloop's
   \@EA\let\@EA\recurselevel\csname\@@irecurse\recursedepth\endcsname
   \global\advance\outerrecurse\minusone}

\def\exitloop                     % \exitloop quits at end
  {\let\endofloop\nodoloop}

\long\def\exitloopnow#1\endofloop % \exitloopnow quits directly
  {\nodoloop}

%D The loop is executed at least once, so beware of situations
%D like:
%D
%D \starttyping
%D \doloop {\exitloop some commands}
%D \stoptyping
%D
%D It's just a matter of putting the text into the \type{\if}
%D statement that should be there anyway, like in:
%D
%D \starttyping
%D \doloop {\ifwhatever \exitloop \else some commands\fi}
%D \stoptyping
%D
%D You can also quit a loop immediately, by using \type
%D {\exitloopnow} instead. Beware, this is more sensitive
%D for conditional errors.

%D Krzysztof Leszczynski suggested to provide access to the level by
%D means of a \type {#1}. I decided to pass the more frequently used
%D level as \type {#1} and the less favoured depth as \type {#2}. The
%D intended usage is:
%D
%D \starttyping
%D \dorecurse{3}{\definesymbol[test-#1][xx-#1]}
%D
%D \def\test{\dorecurse{3}{\definesymbol[test-##1][xx-##1]}} \test
%D
%D \symbol[test-1]\quad\symbol[test-2]\quad\symbol[test-3]
%D \stoptyping
%D
%D Since the hashed arguments are expanded, we don't need tricky
%D expansion here.
%D
%D \starttyping
%D \dorecurse{3}{\expanded{\definesymbol[test-\recurselevel][xx-\recurselevel]}}
%D \stoptyping

\def\expandrecursecontent
  {\csname\@@arecurse\recursedepth\@EA\@EA\@EA\endcsname\@EA\@EA\@EA{\@EA\recurselevel\@EA}\@EA{\recursedepth}}

\long\def\xdorecurse#1#2%
  {\global\advance\outerrecurse \plusone
   \long\global\@EA\def\csname\@@arecurse\recursedepth\endcsname##1##2{#2}%
   \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
   \@EA\dodorecurse\@EA1\@EA{\number#1}}

\long\def\ydorecurse#1#2%
  {\global\advance\outerrecurse \plusone
   \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
   \let\recurselevel\!!plusone
   \long\global\@EA\def\csname\@@arecurse\recursedepth\endcsname##1##2{#2}%
   \expandrecursecontent
   \@EA\let\@EA\recurselevel\csname\@@irecurse\recursedepth\endcsname
   \global\advance\outerrecurse \minusone}

\long\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
  {\global\advance\outerrecurse \plusone
   \long\global\@EA\def\csname\@@arecurse\recursedepth\endcsname##1##2{#4}%
   \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
   \ifnum#3>0\relax
     \ifnum#2<#1\relax
       \let\nextrecurse\exitstepwiserecurse
     \else
       \let\nextrecurse\dodostepwiserecurse
     \fi
   \else
     \ifnum#3<0\relax
       \ifnum#1<#2\relax
         \let\nextrecurse\exitstepwiserecurse
       \else
         \let\nextrecurse\dodostepwisereverse
       \fi
     \else
       \let\nextrecurse\exitstepwiserecurse
     \fi
   \fi\expanded{\nextrecurse{\number#1}{\number#2}{\number#3}}}

\long\def\doloop#1%
  {\global\advance\outerrecurse \plusone
   \long\global\@EA\def\csname\@@arecurse\recursedepth\endcsname##1##2{#1}%
   \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
   \let\endofloop\dodoloop
   \dodoloop1} % no \plusone else \recurselevel wrong

%D For special purposes:

\newcount\fastrecursecounter
\newcount\lastrecursecounter
\newcount\steprecursecounter

\def\dofastrecurse#1#2#3#4%
  {\def\fastrecursebody{#4}%
   \fastrecursecounter#1\relax
   \lastrecursecounter#2\relax
   \steprecursecounter#3\relax
   \def\recurselevel{\number\fastrecursecounter}%
   \dodofastrecurse}

\def\resetrecurselevel{\let\recurselevel\!!zerocount}

\def\dodofastrecurse
  {\ifnum\fastrecursecounter>\lastrecursecounter
     % \resetrecurselevel % slows down
   \else
     \fastrecursebody
     \advance\fastrecursecounter\steprecursecounter
     \expandafter\dodofastrecurse
   \fi}

% \appendtoks \resetrecurselevel \to \everydump

\everydump\expandafter{\the\everydump\resetrecurselevel}

%D This alternative looks a bit different and uses a
%D pseudo counter. When this macro is nested, we have to use
%D different counters. This time we use keywords.
%D
%D \starttyping
%D \def\alfa{2} \def\beta{100} \def\gamma{3}
%D
%D \for \n=55    \to 100   \step  1      \do {... \n ...}
%D \for \n=\alfa \to \beta \step  \gamma \do {... \n ...}
%D \for \n=\n    \to 120   \step  1      \do {... \n ...}
%D \for \n=120   \to 100   \step -3      \do {... \n ...}
%D \for \n=55    \to 100   \step  2      \do {... \n ...}
%D \stoptyping
%D
%D Only in the third example we need to predefine \type{\n}.
%D The use of \type{\od} as a dilimiter would have made nested
%D use more problematic.

%D Don't use this one, it's kind of obsolete.

\def\for#1=#2\to#3\step#4\do#5%
  {\dostepwiserecurse{#2}{#3}{#4}
     {\let#1\recurselevel#5\let#1\recurselevel}}

%D \macros
%D   {newevery,everyline,EveryLine,EveryPar}
%D
%D Lets skip to something quite different. It's common use
%D to use \type{\everypar} for special purposes. In \CONTEXT\
%D we use this primitive for locating sidefloats. This means
%D that when user assignments to \type{\everypar} can interfere
%D with those of the package. We therefore introduce
%D \type{\EveryPar}.
%D
%D The same goes for \type{\EveryLine}. Because \TEX\ offers
%D no \type{\everyline} primitive, we have to call for
%D \type{\everyline} when we are working on a line by line
%D basis. Just by calling \type{\EveryPar{}} and
%D \type{\EveryLine{}} we restore the old situation.
%D
%D The definition command \type{\DoWithEvery} will be quite
%D unreadable, so let's first show an implementation that
%D shows how things are done:
%D
%D \starttyping
%D \newtoks \everyline
%D \newtoks \oldeveryline
%D \newif   \ifeveryline
%D
%D \def\DoWithEvery#1#2#3#4%
%D   {#3\else\edef\next{\noexpand#2={\the#1}}\next\fi
%D    \edef\next{\noexpand#1={\the#2\the\scratchtoks}}\next
%D    #4}
%D
%D \def\doEveryLine%
%D   {\DoWithEvery\everyline\oldeveryline\ifeveryline\everylinetrue}
%D
%D \def\EveryLine%
%D   {\afterassignment\doEveryLine\scratchtoks}
%D \stoptyping
%D
%D The real implementation is a bit more complicated but we
%D prefer something more versatile.

% the old one
%
% \def\DoWithEvery#1%
%   {\csname if\strippedcsname#1\endcsname \else
%      \edef\next%
%        {\@EA\noexpand\csname old\strippedcsname#1\endcsname=
%           {\the#1}}%
%      \next
%    \fi
%    \edef\next%
%      {\noexpand#1=
%         {\@EA\the\csname old\strippedcsname#1\endcsname\the\scratchtoks}}%
%    \next
%    \csname\strippedcsname#1true\endcsname}
%
% \def\dowithevery#1%
%   {\@EA\afterassignment\csname do\strippedcsname#1\endcsname\scratchtoks}
%
% \def\newevery#1#2%
%   {\ifx#1\undefined\newtoks#1\fi
%    \ifx#2\relax\else\ifx#2\undefined
%      \@EA\newtoks\csname old\strippedcsname#1\endcsname
%      \@EA\newif  \csname  if\strippedcsname#1\endcsname
%      \@EA\def    \csname  do\strippedcsname#2\endcsname{\DoWithEvery#1}%
%      \def#2{\dowithevery#2}%
%    \fi\fi}
%
% cleaner and more efficient

%\def\dowithevery#1%
%  {\def\dodowithevery%
%     {\ifcase\csname c\strippedcsname#1\endcsname \expandafter\chardef
%        \csname c\strippedcsname#1\endcsname=1
%        \csname t\strippedcsname#1\endcsname=#1%
%      \fi
%      \edef\next%
%        {#1={\the\csname t\strippedcsname#1\endcsname\the\scratchtoks}}%
%      \next}%
%  \afterassignment\dodowithevery\scratchtoks}
%
% more efficient:

\def\dodowithevery#1%
  {\ifcase\csname c\strippedcsname#1\endcsname \expandafter\chardef
      \csname c\strippedcsname#1\endcsname1
      \csname t\strippedcsname#1\endcsname#1%
    \fi
    \edef\next%
      {#1{\the\csname t\strippedcsname#1\endcsname\the\scratchtoks}}%
    \next}

\def\dowithevery#1%
  {\def\next{\dodowithevery#1}%
   \afterassignment\next\scratchtoks}

\bgroup \let\newtoks\relax % plain safe (\outer)

\gdef\newevery#1#2%
  {\ifx#1\undefined\csname newtoks\endcsname#1\fi % plain safe (\outer)
   \ifx#2\relax\else\ifx#2\undefined
     \expandafter\newtoks\csname t\strippedcsname#1\endcsname
     \expandafter\chardef\csname c\strippedcsname#1\endcsname\zerocount
     \def#2{\dowithevery#1}%
   \fi\fi}

\egroup

%D The first \type {\outer} hack is needed to trick \TEX\
%D into thinking that \type {\newtoks} is no outer macro,
%D the second hack is needed due to some funny interaction
%D between outer macros and \type {\if} at expansion time.

%D This one permits definitions like:

\newevery \everypar  \EveryPar
\newevery \everyline \EveryLine

%D and how about:

\newevery \neverypar  \NeveryPar

%D Which we're going to use indeed! When the second argument
%D equals \type {\relax}, the first token list is created
%D unless it is already defined.

%D Technically spoken we could have used the method we are
%D going to present in the visual debugger. First we save
%D the primitive \type{\everypar}:
%D
%D \starttyping
%D \let\normaleverypar=\everypar
%D \stoptyping
%D
%D Next we allocate a \TOKENLIST\ named \type{\everypar},
%D which means that \type{\everypar} is no longer a primitive
%D but something like \type{\toks44}.
%D
%D \starttyping
%D \newtoks\everypar
%D \stoptyping
%D
%D Because \TEX\ now executes \type{\normaleverypar} instead
%D of \type{\everypar}, we are ready to assign some tokens to
%D this internally known and used \TOKENLIST.
%D
%D \starttyping
%D \normaleverypar={all the things the system wants to do \the\everypar}
%D \stoptyping
%D
%D Where the user can provide his own tokens to be expanded
%D every time he expects them to expand.
%D
%D \starttyping
%D \everypar={something the user wants to do}
%D \stoptyping
%D
%D We don't use this method because it undoubtly leads to
%D confusing situations, especially when other packages are
%D used, but it's this kind of tricks that make \TEX\ so
%D powerful.

%D \macros
%D   {convertargument,convertcommand,convertvalue}
%D
%D Some persistent experimenting led us to the next macro. This
%D macro converts a parameter or an expanded macro to it's
%D textual meaning.
%D
%D \starttyping
%D \convertargument ... \to \command
%D \stoptyping
%D
%D For example,
%D
%D \starttyping
%D \convertargument{one \two \three{four}}\to\ascii
%D \stoptyping
%D
%D The resulting macro \type{\ascii} can be written to a file
%D or the terminal without problems. In \CONTEXT\ we use this
%D macro for generating registers and tables of contents.
%D
%D The second conversion alternative accepts a command:
%D
%D \starttyping
%D \convertcommand\command\to\ascii
%D \stoptyping
%D
%D Both commands accept the prefix \type{\doglobal} for global
%D assignments.

\beginTEX

\def\doconvertargument#1>{}

\def\convertedcommand
  {\expandafter\doconvertargument\meaning}

\long\def\convertargument#1\to#2%
  {\long\def#2{#1}% saves a restore
   \dodoglobal\edef#2{\convertedcommand#2}}

\long\def\convertcommand#1\to#2%
  {\dodoglobal\edef#2{\convertedcommand#1}}

% no dodoglobal !

\long\def\defconvertedargument#1#2% less sensitive for \to
  {\long\def#1{#2}% saves a restore
   \edef#1{\convertedcommand#1}}

\long\def\defconvertedcommand#1#2% less sensitive for \to
  {\edef#1{\convertedcommand#2}}

\long\def\gdefconvertedargument#1#2% less sensitive for \to
  {\long\gdef#1{#2}% saves a restore
   \xdef#1{\convertedcommand#1}}

\long\def\gdefconvertedcommand#1#2% less sensitive for \to
  {\xdef#1{\convertedcommand#2}}

\endTEX

\def\convertvalue#1\to
  {\expandafter\convertcommand\csname#1\endcsname\to}

\def\defconvertedvalue#1#2% less sensitive for \to
  {\@EA\defconvertedcommand\@EA#1\csname#2\endcsname}

%D \macros
%D   {doifassignmentelse}
%D
%D A lot of \CONTEXT\ commands take optional arguments, for
%D instance:
%D
%D \starttyping
%D \dothisorthat[alfa,beta]
%D \dothisorthat[first=foo,second=bar]
%D \dothisorthat[alfa,beta][first=foo,second=bar]
%D \stoptyping
%D
%D Although a combined solution is possible, we prefer a
%D seperation. The next command takes care of propper
%D handling of such multi||faced commands.
%D
%D \starttyping
%D \doifassignmentelse {...} {then ...} {else ...}
%D \stoptyping

% not robust
%
% \def\doifassignmentelse%
%   {\doifinstringelse{=}}
%
% readable
%
% \def\doifassignmentelse#1%
%   {\convertargument#1\to\ascii
%    \doifinstringelse{=}{\ascii}}

\def\doifassignmentelse#1%
  {\convertargument#1\to\ascii
   \doifinstringelse=\ascii}

%D \macros
%D   {convertasciiafter}
%D
%D Sometimes we need to convert an argument to a string (letters
%D only), for instance when we compare it with another string:
%D
%D \starttyping
%D \convertasciiafter\doifinstringelse{em}{\ascii}{...}
%D \stoptyping

\def\convertasciiafter#1#2%
  {\convertargument#2\to\asciiafter
   \@EA#1\@EA{\asciiafter}}

%D In \ETEX\ we can use \type {\detokenize} and gain some
%D speed, but in general far less that 1\% for \type
%D {\convertargument} and nil for \type {\convertcommand}.
%D This macro is more robust than the pure \TEX\ one,
%D something I found out when primitives like \type
%D {\jobname} were fed (or something undefined).

% command variant: one level expansion !

\beginETEX \detokenize

\long\def\convertargument#1\to#2{\dodoglobal\edef#2{\detokenize{#1}}}
\long\def\convertcommand #1\to#2{\dodoglobal\edef#2{\@EA\detokenize\@EA{#1}}} % hm, only second is also ok

\long\def\defconvertedargument #1#2{\edef#1{\detokenize    {#2}}}
\long\def\defconvertedcommand  #1#2{\edef#1{\detokenize\@EA{#2}}}
\long\def\edefconvertedargument#1#2{\edef#1{#2}%
                                    \edef#1{\detokenize\@EA{#1}}}
\long\def\gdefconvertedargument#1#2{\xdef#1{\detokenize    {#2}}}
\long\def\gdefconvertedcommand #1#2{\xdef#1{\detokenize\@EA{#2}}}
\long\def\xdefconvertedargument#1#2{\xdef#1{#2}%
                                    \xdef#1{\detokenize\@EA{#1}}}

\endETEX

%D When you try to convert a primitive command, you'll find
%D out that the \ETEX\ method fails on for instance \type
%D {\jobname} in the sense that it returns the filename
%D instead of just \type {\jobname}. So far this does not
%D give real problems.

%D This is typically a macro that one comes to after reading
%D the \TEX book carefully. Even then, the definite solution
%D was found after rereading the \TEX book. The first
%D implementation was:
%D
%D \starttyping
%D \def\doconvertargument#1->#2\\\\{#2}
%D \stoptyping
%D
%D The \type{-}, the delimiter \type{\\\\} and the the second
%D argument are completely redundant.

%D \macros
%D   {showvalue,showargument}
%D
%D Two handy macros for testing purposes only:

\def\showvalue#1%
  {\expandafter\show\csname#1\endcsname}

\beginETEX

\def\showvalue#1%
  {\ifcsname#1\endcsname
     \expandafter\show\csname#1\endcsname
   \else
     \show\undefined
   \fi}

\endETEX

\long\def\showargument#1%
  {\defconvertedargument\ascii{#1}\ascii}

%D \macros
%D   {doifmeaningelse}
%D
%D We can use both commands in testing, but alas, not all
%D meanings expand to something \type {->}. This is no problem
%D in the \ETEX\ implementation, but since we want
%D compatibility, we need:
%D
%D \starttyping
%D \doifmeaningelse {\next} {\something} {true} {false}
%D \stoptyping
%D
%D Watch the one level expansion of the second argument.

\def\doifmeaningelse#1#2%
  {\edef\!!stringa{\meaning#1}%
   \def\!!stringb{#2}\edef\!!stringb{\meaning\!!stringb}%
   \ifx\!!stringa\!!stringb
     \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

%D \macros
%D   {doifsamestringselse,doifsamestring,doifnotsamestring}
%D
%D The next comparison macro converts the arguments into
%D expanded strings. This command can be used to compare for
%D instance \type {\jobname} with a name stored in a macro.

\def\@@doifsamestringelse#1#2%
  {\edef\!!stringa{#1}%
   \edef\!!stringb{#2}%
   \convertcommand\!!stringa\to\!!stringa
   \convertcommand\!!stringb\to\!!stringb
   \ifx\!!stringa\!!stringb}

\def\doifsamestringelse#1#2%
  {\@@doifsamestringelse{#1}{#2}%
     \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

\def\doifsamestring#1#2%
  {\@@doifsamestringelse{#1}{#2}%
     \expandafter\firstofoneargument
   \else
     \expandafter\gobbleoneargument
   \fi}

\def\doifnotsamestring#1#2%
  {\@@doifsamestringelse{#1}{#2}%
     \expandafter\gobbleoneargument
   \else
     \expandafter\firstofoneargument
   \fi}

%D \macros
%D   {ExpandFirstAfter,ExpandSecondAfter,ExpandBothAfter}
%D
%D These three commands support expansion of arguments before
%D executing the commands that uses them. We can best
%D illustrate this with an example.
%D
%D \starttyping
%D \def\first  {alfa,beta,gamma}
%D \def\second {alfa,epsilon,zeta}
%D
%D \ExpandFirstAfter  \doifcommon {\first} {alfa}    {\message{OK}}
%D \ExpandSecondAfter \doifcommon {alfa}   {\second} {\message{OK}}
%D \ExpandBothAfter   \doifcommon {\first} {\second} {\message{OK}}
%D
%D \ExpandFirstAfter\processcommalist[\first]\message
%D
%D \ExpandAfter       \doifcommon {\first} {alfa}    {\message{OK}}
%D \stoptyping
%D
%D The first three calls result in the threefold message
%D \type{OK}, the fourth one shows the three elements of
%D \type{\first}. The command \type{\ExpandFirstAfter} takes
%D care of (first) arguments that are delimited by \type{[ ]},
%D but the faster \type{\ExpandAfter} does not.

\def\simpleExpandFirstAfter#1%
  {\long\xdef\@@expanded{\noexpand\ExpandCommand{#1}}\@@expanded}

\def\complexExpandFirstAfter[#1]%
  {\long\xdef\@@expanded{\noexpand\ExpandCommand[#1]}\@@expanded}

\def\ExpandFirstAfter#1%
  {\let\ExpandCommand#1%
   \doifnextoptionalelse\complexExpandFirstAfter\simpleExpandFirstAfter}

\def\ExpandSecondAfter#1#2#3%
  {\scratchtoks{#2}%
   \long\xdef\@@expanded{\noexpand#1{\the\scratchtoks}{#3}}\@@expanded}

\def\ExpandBothAfter#1#2#3%
  {\long\xdef\@@expanded{\noexpand#1{#2}{#3}}\@@expanded}

\def\ExpandAfter#1#2%
  {\long\xdef\@@expanded{\noexpand#1{#2}}\@@expanded}

%D Now we can for instance define \type{\ifinstringelse} as:

\def\ifinstringelse
  {\ExpandBothAfter\p!doifinstringelse}

%D \macros
%D   {ConvertToConstant,ConvertConstantAfter}
%D
%D When comparing arguments with a constant, we can get into
%D trouble when this argument consists of tricky expandable
%D commands. One solution for this is converting the
%D argument to a string of unexpandable characters. To make
%D comparison possible, we have to convert the constant too
%D
%D \starttyping
%D \ConvertToConstant\doifelse {...} {...} {then ...} {else ...}
%D \stoptyping
%D
%D This construction is only needed when the first argument
%D can give troubles. Misuse can slow down processing.
%D
%D \starttyping
%D \ConvertToConstant\doifelse{\c!alfa}        {\c!alfa}{...}{...}
%D \ConvertToConstant\doifelse{alfa}           {\c!alfa}{...}{...}
%D \ConvertToConstant\doifelse{alfa}           {alfa}   {...}{...}
%D \ConvertToConstant\doifelse{alfa \alfa test}{\c!alfa}{...}{...}
%D \stoptyping
%D
%D In examples~2 and~3 both arguments equal, in~1 and~4
%D they differ.

\beginTEX

\long\def\ConvertToConstant#1#2#3%
  {\expandafter\defconvertedargument\expandafter\!!stringa\expandafter{#2}%
   \expandafter\defconvertedargument\expandafter\!!stringb\expandafter{#3}%
   #1{\!!stringa}{\!!stringb}}

\endTEX

\beginETEX \detokenize

\long\def\ConvertToConstant#1#2#3%
  {\edef\!!stringa{\expandafter\detokenize\expandafter{#2}}%
   \edef\!!stringb{\expandafter\detokenize\expandafter{#3}}%
   #1{\!!stringa}{\!!stringb}}

\endETEX

%D When the argument \type{#1} consists of commands, we had
%D better use
%D
%D \starttyping
%D \ConvertConstantAfter\processaction[#1][...]
%D \ConvertConstantAfter\doifelse{#1}{\v!something}{}{}
%D \stoptyping
%D
%D This commands accepts things like:
%D
%D \starttyping
%D \v!constant
%D constant
%D \hbox to \hsize{\rubish}
%D \stoptyping
%D
%D As we will see in the core modules, this macro permits
%D constructions like:
%D
%D \starttyping
%D \setupfootertexts[...][...]
%D \setupfootertexts[margin][...][...]
%D \setupfootertexts[\v!margin][...][...]
%D \stoptyping
%D
%D where \type{...} can be anything legally \TEX.

\def\CheckConstantAfter#1#2%
  {\@EA\convertargument\v!prefix!\to\ascii
   \convertargument#1\to#2\relax
   \doifinstringelse\ascii{#2}
     {\expandafter\convertargument#1\to#2}
     {}}

\def\ConvertConstantAfter#1#2#3%
  {\CheckConstantAfter{#2}\asciia
   \CheckConstantAfter{#3}\asciib
   #1{\asciia}{\asciib}}

%D \macros
%D   {assignifempty}
%D
%D We can assign a default value to an empty macro using:
%D
%D \starttyping
%D \assignifempty \macros {default value}
%D \stoptyping
%D
%D We don't explicitly test if the macro is defined.

\def\assignifempty#1#2% can be sped up
  {\doifsomething{#1}{\def#1{#2}}} % {\doifnot{#1}{}{\def#1{#2}}}

%D \macros
%D   {gobbleuntil,grabuntil,gobbleuntilrelax,
%D    processbetween,processuntil}
%D
%D In \TEX\ gobbling usually stand for skipping arguments, so
%D here are our gobbling macros.
%D
%D In \CONTEXT\ we use a lot of \type{\start}||\type{\stop}
%D like constructions. Sometimes, the \type{\stop} is used as a
%D hard coded delimiter like in:
%D
%D \starttyping
%D \def\startcommand#1\stopcommand%
%D   {... #1 ...}
%D \stoptyping
%D
%D In many cases the \type{\start}||\type{\stop} pair is
%D defined at format generation time or during a job. This
%D means that we cannot hardcode the \type{\stop} criterium.
%D Only after completely understanding \type{\csname} and
%D \type{\expandafter} I was able to to implement a solution,
%D starting with:
%D
%D \starttyping
%D \grabuntil{stop}\command
%D \stoptyping
%D
%D This commands executes, after having encountered
%D \type {\stop} the command \type {\command}. This command
%D receives as argument the text preceding the \type {\stop}.
%D This means that:
%D
%D \starttyping
%D \def\starthello%
%D   {\grabuntil{stophello}\message}
%D
%D \starthello Hello world!\stophello
%D \stoptyping
%D
%D results in: \type{\message{Hello world!}}.

\def\dograbuntil#1#2%
  {\long\def\next##1#1{#2{##1}}\next}

\def\grabuntil#1%
  {\expandafter\dograbuntil\expandafter{\csname#1\endcsname}}

%D The next command build on this mechanism:
%D
%D \starttyping
%D \processbetween{string}\command
%D \stoptyping
%D
%D Here:
%D
%D \starttyping
%D \processbetween{hello}\message
%D \starthello Hello again!\stophello
%D \stoptyping
%D
%D leads to: \type{\message{Hello again!}}. The command
%D
%D \starttyping
%D \gobbleuntil{sequence}
%D \stoptyping
%D
%D is related to these commands. This one simply throws away
%D everything preceding \type{\command}.

\long\def\processbetween#1#2%
  {\setvalue{\s!start#1}{\grabuntil{\s!stop#1}{#2}}}

\def\gobbleuntil#1%
  {\long\def\next##1#1{}\next}

\def\gobbleuntilrelax#1\relax
  {}

%D The next one simply expands the pickup up tokens.
%D
%D \starttyping
%D \processuntil{sequence}
%D \stoptyping

\def\processuntil#1%
  {\long\def\next##1#1{##1}\next}

%D \macros
%D   {groupedcommand}
%D
%D Commands often manipulate argument as in:
%D
%D \starttyping
%D \def\doezomaarwat#1{....#1....}
%D \stoptyping
%D
%D A disadvantage of this approach is that the tokens that
%D form \type{#1} are fixed the the moment the argument is read
%D in. Normally this is no problem, but for instance verbatim
%D environments adapt the \CATCODES\ of characters and therefore
%D are not always happy with already fixed tokens.
%D
%D Another problem arises when the argument is grouped not by
%D \type{{}} but by \type{\bgroup} and \type{\egroup}. Such an
%D argument fails, because the \type{\bgroup} is een as the
%D argument (which is quite normal).
%D
%D The next macro offers a solution for both unwanted
%D situations:
%D
%D \starttyping
%D \groupedcommand {before} {after}
%D \stoptyping
%D
%D Which can be used like:
%D
%D \starttyping
%D \def\cite%
%D   {\groupedcommand{\rightquote\rightquote}{\leftquote\leftquote}}
%D \stoptyping
%D
%D This command is equivalent to, but more 'robust' than:
%D
%D \starttyping
%D \def\cite#1%
%D   {\rightquote\rightquote#1\leftquote\leftquote}
%D \stoptyping
%D
%D One should say that the next implementation would suffice:
%D
%D \starttyping
%D \def\groupedcommand#1#2%
%D   {\def\BeforeGroup{#1\ignorespaces}%
%D    \def\AfterGroup{\unskip#2\egroup}%
%D    \bgroup\bgroup
%D    \aftergroup\AfterGroup
%D    \afterassignment\BeforeGroup
%D    \let\next=}
%D \stoptyping
%D
%D It did indeed, but one day we decided to support the
%D processing of boxes too:
%D
%D \starttyping
%D \def\rightword%
%D   {\groupedcommand{\hfill\hbox}{\parfillskip\!!zeropoint}}
%D
%D .......... \rightword{the right way}
%D \stoptyping
%D
%D Here \TEX\ typesets \type{\bf the right way} unbreakable
%D at the end of the line. The solution mentioned before does
%D not work here.
%D
%D \starttyping
%D \long\unexpanded\def\groupedcommand#1#2%
%D   {\bgroup
%D    \long\def\BeforeGroup%
%D      {\bgroup#1\bgroup\aftergroup\AfterGroup}%
%D    \long\def\AfterGroup%
%D      {#2\egroup\egroup}%
%D    \afterassignment\BeforeGroup
%D    \let\next=}
%D \stoptyping
%D
%D We used this method some time until the next alternative
%D was needed. From now on we support both
%D
%D \starttyping
%D to be \bold{bold} or not, that's the question
%D \stoptyping
%D
%D and
%D
%D \starttyping
%D to be {\bold bold} or not, that's the question
%D \stoptyping
%D
%D This alternative checks for a \type{\bgroup} token first.
%D The internal alternative does not accept the box handling
%D mentioned before, but further nesting works all right. The
%D extra \type{\bgroup}||\type{\egroup} is needed to keep
%D \type{\AfterGroup} both into sight and local.

\long\def\HandleGroup#1#2%
  {\bgroup
   \long\def\BeforeGroup{\bgroup#1\bgroup\aftergroup\AfterGroup}%
   \long\def\AfterGroup {#2\egroup\egroup}%
   \afterassignment\BeforeGroup
   \let\next=}

\long\def\HandleSimpleGroup#1#2% no inner group (so no kerning interference)
  {\bgroup
   %long\def\BeforeGroup{\bgroup#1\aftergroup\AfterGroup}% interferes
   \long\def\BeforeGroup{\bgroup\aftergroup\AfterGroup#1}%
   \long\def\AfterGroup {#2\egroup}%
   \afterassignment\BeforeGroup
   \let\next=}

\long\def\HandleNoGroup#1#2%
  {\long\def\AfterGroup{#2\egroup}%
   \bgroup\aftergroup\AfterGroup#1}

%D These macros come together in:
%D
%D \starttyping
%D \long\unexpanded\def\groupedcommand#1#2%
%D   {\def\dogroupedcommand%
%D      {\ifx\next\bgroup
%D         \let\next=\HandleGroup
%D       \else
%D         \let\next=\HandleNoGroup
%D       \fi
%D       \next{#1}{#2}}%
%D    \futurelet\next\dogroupedcommand}
%D \stoptyping
%D
%D From the missing paragraph number one can deduce that the
%D last macro is not the real one yet. I considered it a
%D nuisance that
%D
%D \starttyping
%D \color[green]
%D   {as grass}
%D \stoptyping
%D
%D was not interpreted as one would expect. This is due to the
%D fact that \type{\futurelet} obeys blank spaces, and a
%D line||ending token is treated as a blank space. So the final
%D implementation became:

%\long\unexpanded\def\groupedcommand#1#2%
%  {\bgroup
%   \def\dogroupedcommand%
%     {\ifx\next\bgroup
%        \def\\{\egroup\HandleGroup{#1}{#2}}%
%      \else\ifx\next\blankspace
%        \def\\ {\egroup\groupedcommand{#1}{#2}}%
%      \else
%        \def\\{\egroup\HandleNoGroup{#1}{#2}}%
%      \fi\fi
%      \\}%
%   \futurelet\next\dogroupedcommand}
%
% compatible ?

\long\unexpanded\def\groupedcommand#1#2%
  {\doifnextbgroupelse{\HandleGroup{#1}{#2}}{\HandleNoGroup{#1}{#2}}}

\long\unexpanded\def\simplegroupedcommand#1#2%
  {\doifnextbgroupelse{\HandleSimpleGroup{#1}{#2}}{\HandleNoGroup{#1}{#2}}}

%D Users should be aware of the fact that grouping can
%D interfere with ones paragraph settings that are executed
%D after the paragraph is closed. One should therefore
%D explictly close the paragraph with \type{\par}, else the
%D settings will be forgotten and not applied. So it's:
%D
%D \starttyping
%D \def\BoldRaggedCenter%
%D   {\groupedcommand{\raggedcenter\bf}{\par}}
%D \stoptyping

%D \macros
%D   {checkdefined}
%D
%D The bigger the system, the greater the change that
%D user defined commands collide with those that are part of
%D the system. The next macro gives a warning when a command is
%D already defined. We considered blocking the definition, but
%D this is not always what we want.
%D
%D \starttyping
%D \checkdefined {category} {class} {command}
%D \stoptyping
%D
%D The user is warned with the suggestion to use
%D \type{CAPITALS}. This suggestion is feasible, because
%D \CONTEXT only defines lowcased macros.

\def\showdefinederror#1#2%
  {\writestatus\m!systems{#1 #2 replaces a macro, use CAPITALS!}}

\def\checkdefined#1#2#3%
  {\doifdefined{#3}{\showdefinederror{#2}{#3}}}

%D \macros
%D   {GotoPar,GetPar}
%D
%D Typesetting a paragraph in a special way can be done by
%D first grabbing the contents of the paragraph and processing
%D this contents grouped. The next macro for instance typesets
%D a paragraph in boldface.
%D
%D \starttyping
%D \def\remark#1\par%
%D   {\bgroup\bf#1\egroup}
%D \stoptyping
%D
%D This macro has to be called like
%D
%D \starttyping
%D \remark some text ... ending with \par
%D \stoptyping
%D
%D Instead of \type{\par} we can of course use an empty line.
%D When we started typesetting with \TEX, we already had
%D produced lots of text in plain \ASCII. In producing such
%D simple formatted texts, we adopted an open layout, and when
%D switching to \TEX, we continued this open habit. Although
%D \TEX\ permits a cramped and badly formatted source, it adds
%D to confusion and sometimes introduces errors. So we prefer:
%D
%D \starttyping
%D \remark
%D
%D some text ... ending with an empty line
%D \stoptyping
%D
%D We are going to implement a mechanism that allows such open
%D specifications. The definition of the macro handling
%D \type{\remark} becomes:
%D
%D \starttyping
%D \def\remark%
%D   {\BeforePar{\bgroup\bf}%
%D    \AfterPar{\egroup}%
%D    \GetPar}
%D \stoptyping
%D
%D A macro like \type{\GetPar} can be defined in several
%D ways. The recent version, the fourth one in a row,
%D originally was far more complicated, but some functionality
%D has been moved to other macros.
%D
%D We start with the more simple but in some cases more
%D appropriate alternative is \type{\GotoPar}. This one leaves
%D \type{\par} unchanged and is therefore more robust. On the
%D other hand, \type{\AfterPar} is not supported.

\newtoks\BeforePar
\newtoks\AfterPar

\let\endoflinetoken=^^M

%D The original definition was:
%D
%D \starttyping
%D \def\doGotoPar
%D   {\ifx\nextchar\blankspace
%D      \@EA\GotoPar
%D    \else\ifx\nextchar\endoflinetoken
%D      \@EAEAEA\GotoPar
%D    \else
%D      \@EAEAEA\dodoGotoPar
%D    \fi\fi}
%D
%D \def\dodoGotoPar
%D   {\the\BeforePar
%D    \BeforePar\emptytoks
%D    \nextchar}
%D
%D \def\GotoPar
%D   {\afterassignment\doGotoPar\let\nextchar=}
%D \stoptyping

%D Its big brother \type{\GetPar} redefines the \type{\par}
%D primitive, which can lead to unexpected results, depending
%D in the context.
%D
%D \starttyping
%D \def\GetPar
%D   {\expanded
%D      {\BeforePar
%D         {\the\BeforePar
%D          \BeforePar\emptytoks
%D          \bgroup
%D          \def\par
%D            {\egroup
%D             \par
%D             \the\AfterPar
%D             \BeforePar\emptytoks
%D             \AfterPar\emptytoks}}}%
%D    \GotoPar}
%D \stoptyping

%D However, we can implement a better alternative by using:
%D
%D \starttyping
%D \def\dowithpar#1#2%
%D   {\def\handlepar##1\par{#1##1#2}%
%D    \def\gobblepar\par{\dowithpar{#1}{#2}}%
%D    \doifnextcharelse\par\gobblepar\handlepar}
%D \stoptyping
%D
%D Or, nicer

\def\redowithpar\par
  {\doifnextcharelse\par\redowithpar\dodowithpar}%

\def\dowithpar#1#2%
  {\def\dodowithpar##1\par{#1##1#2}%
   \redowithpar\par}

\def\redogotopar\par
  {\doifnextcharelse\par\redogotopar\dodogotopar}%

\def\dogotopar#1%
  {\def\dodogotopar{#1}%
   \redogotopar\par}

%D The previosuly defined macros now become:

\def\GetPar
  {\expanded
     {\dowithpar
        {\the\BeforePar
         \BeforePar\emptytoks}
        {\the\AfterPar
         \BeforePar\emptytoks
         \AfterPar\emptytoks}}}

\def\GotoPar
  {\expanded
     {\dogotopar
        {\the\BeforePar
         \BeforePar\emptytoks}}}

%D \macros
%D   {dowithpargument,dowithwargument}
%D
%D The next macros are a variation on \type{\GetPar}. When
%D macros expect an argument, it interprets a grouped sequence
%D of characters a one token. While this adds to robustness and
%D less ambiguous situations, we sometimes want to be a bit
%D more flexible, or at least want to be a bit more tolerant
%D to user input.
%D
%D We start with a commands that acts on paragraphs. This
%D command is called as:
%D
%D \starttyping
%D \dowithpargument\command
%D \dowithpargument{\command ... }
%D \stoptyping
%D
%D In \CONTEXT\ we use this one to read in the titles of
%D chapters, sections etc. The commands responsible for these
%D activities accept several alternative ways of argument
%D passing. In these examples, the \type{\par} can be omitted
%D when an empty line is present.
%D
%D \starttyping
%D \command{...}
%D \command ... \par
%D \command
%D   {...}
%D \command
%D   ... \par
%D \stoptyping
%D
%D We show two implementations, of which for the moment the
%D we prefier to use the second one:
%D
%D \starttyping
%D \def\dowithpargument#1%
%D   {\def\dodowithpargument%
%D      {\ifx\next\bgroup
%D         \def\next{#1}%
%D       \else
%D         \def\next####1 \par{#1{####1}}%
%D       \fi
%D       \next}%
%D    \futurelet\next\dodowithpargument}
%D \stoptyping
%D
%D A second and better implementation was:
%D
%D \starttyping
%D \def\dowithpargument#1%
%D   {\def\nextpar##1 \par{#1{##1}}%
%D    \def\nextarg##1{#1{##1}}%
%D    \doifnextcharelse\bgroup
%D      {\nextarg}
%D      {\nextpar}}
%D \stoptyping
%D
%D We ended up with an alternative that also accepts en empty
%D argument. This command permits for instance chapters to
%D have no title.

%\def\dowithpargument#1%
%  {\def\nextpar##1 \par{#1{##1}}%
%   \def\nextarg##1{#1{##1}}%
%   \doifnextcharelse\bgroup
%     {\nextarg}
%     {\doifnextcharelse{\par}
%        {#1{}}
%        {\nextpar}}}

\def\dowithpargument#1%
  {\def\nextpar##1 \par{#1{##1}}%
   \def\nextarg##1{#1{##1}}%
   \doifnextbgroupelse\nextarg{\doifnextcharelse\par{#1{}}\nextpar}}

%D The \type{p} in the previous command stands for paragraph.
%D When we want to act upon words we can use the \type{w}
%D alternative.
%D
%D \starttyping
%D \dowithwargument\command
%D \dowithwargument{... \command ...}
%D \stoptyping
%D
%D The main difference bwteen two alternatives is in the
%D handling of \type{\par}'s. This time the space token acts
%D as a delimiter.
%D
%D \starttyping
%D \command{...}
%D \command ...
%D \command
%D   {...}
%D \command
%D   ...
%D \stoptyping
%D
%D Again there are two implementations possible:
%D
%D \starttyping
%D \def\dowithwargument#1%
%D   {\def\dodowithwargument%
%D      {\ifx\next\bgroup
%D         \def\next{#1}%
%D       \else
%D         \def\next####1 {#1{####1}}%
%D       \fi
%D       \next}%
%D    \futurelet\next\dodowithwargument}
%D \stoptyping
%D
%D We've chosen:

%\def\dowithwargument#1%
%  {\def\nextwar##1 {#1{##1}}%
%   \def\nextarg##1{#1{##1}}%
%   \doifnextcharelse\bgroup
%     {\nextarg}
%     {\nextwar}}

\def\dowithwargument#1%
  {\def\nextwar##1 {#1{##1}}%
   \def\nextarg##1{#1{##1}}%
   \doifnextbgroupelse\nextarg\nextwar}

%D \macros
%D   {dorepeat,dorepeatwithcommand}
%D
%D When doing repetitive tasks, we stromgly advice to use
%D \type{\dorecurse}. The next alternative however, suits
%D better some of the \CONTEXT\ interface commands.
%D
%D \starttyping
%D \dorepeat[n*\command]
%D \stoptyping
%D
%D The value of the used \COUNTER\ can be called within
%D \type{\command} by \type{\repeater}.
%D
%D A slightly different alternative is:
%D
%D \starttyping
%D \dorepeatwithcommand[n*{...}]\command
%D \stoptyping
%D
%D When we call for something like:
%D
%D \starttyping
%D \dorepeatwithcommand[3*{Hello}]\message
%D \stoptyping
%D
%D we get ourselves three \type{\message{Hello}} messages in
%D a row. In both commands, the \type{n*} is optional. When this
%D specification is missing, the command executes once.

% this one is obsolete:

\def\dorepeat[#1]%
  {\dodorepeat#1*\empty*\relax}

\long\def\dodorepeat#1*#2#3*#4\relax
  {\ifx#2\empty#1\else\dorecurse{#1}{#2#3}\fi}

\def\repeater
  {\recurselevel}

% this one will be kept

\def\dorepeatwithcommand[#1]%
  {\dodorepeatwithcommand#1*\empty*\relax}

% \long\def\dodorepeatwithcommand#1*#2#3*#4\relax#5%
%   {\ifx#2\empty
%      #5{#1}%
%    \else
%      \dorecurse{#1}{#5{#2#3}}%
%    \fi}
%
% more complex but better:

% \long\def\dodorepeatwithcommand#1*#2#3*#4\relax#5%
%   {\ifx#2\empty
%      #5{#1}%
%    \else\ifnum#1<\zerocount
%      % a la etex
%      % \dorecurse{-\numexpr(#1)}{#5{-#2#3}}%
%      % indirect
%      %\innerrecurse#1%
%      %\expanded{\dorecurse{\number-\innerrecurse}}{#5{-#2#3}}%
%      % safer:
%      \bgroup\scratchcounter#1%
%      \expanded{\egroup\noexpand\dorecurse{\number-\scratchcounter}}{#5{-#2#3}}%
%    \else\ifx#2+%
%      \dorecurse{#1}{#5{#3}}%
%    \else
%      \dorecurse{#1}{#5{#2#3}}%
%    \fi\fi\fi}

\def\dorepeatwithcommand[#1]%
  {\dodorepeatwithcommand#1*\empty*\relax}

\long\def\dodorepeatwithcommand#1*#2#3*#4\relax#5%
  {\ifx#2\empty\redorepeatwithcommand[#1]#5\else\dododorepeatwithcommand{#1}{#2}{#3}#5\fi}

\long\def\dododorepeatwithcommand#1#2#3#4%
  {\ifx#2\empty % redundant but gives cleaner extensions
     #4{#1}%
   \else\ifnum#1<\zerocount
     \bgroup\scratchcounter#1%
     \expanded{\egroup\noexpand\dorecurse{\number-\scratchcounter}}{#4{-#2#3}}%
   \else\ifx#2+%
     \dorecurse{#1}{#4{#3}}%
   \else
     \dorecurse{#1}{#4{#2#3}}%
   \fi\fi\fi}

\def\redorepeatwithcommand[#1]#2%
  {#2{#1}}

%D The extension hook permits something like:
%D
%D \starttyping
%D \bgroup
%D
%D \catcode`\*=\@@superscript
%D
%D \gdef\redorepeatwithcommand[#1]%
%D   {\redodorepeatwithcommand#1*\empty*\relax}
%D
%D \long\gdef\redodorepeatwithcommand#1*#2#3*#4\relax#5%
%D   {\dododorepeatwithcommand{#1}{#2}{#3}#5}
%D
%D \egroup
%D \stoptyping
%D
%D although one may wonder if changing the catcode of \type {*} is wise.

%D \macros
%D   {normalbgroup,normalgroup}
%D
%D No comment.

\let\normalbgroup\bgroup
\let\normalegroup\egroup

%D \macros
%D   {doifstringinstringelse}
%D
%D The next macro is meant for situations where both strings
%D are macros. This save some unneeded expansion.
%D
%D \starttyping
%D \long\def\doifstringinstringelse#1#2%
%D   {\p!doifinstringelse#1#2%
%D      \@EA\firstoftwoarguments
%D    \else
%D      \@EA\secondoftwoarguments
%D    \fi}
%D \stoptyping
%D
%D A bit faster is:

\def\pp!doifstringinstringelse#1%
  {\if#1@%
     \@EA\secondoftwoarguments
   \else
     \@EA\firstoftwoarguments
   \fi}

\long\def\doifstringinstringelse#1#2%
  {\long\@EA\def\@EA\p!doifstringinstringelse\@EA##\@EA1#1##2##3\war
     {\pp!doifstringinstringelse##2}%
   \@EA\@EA\@EA\p!doifstringinstringelse\@EA#2#1@@\war}

%D \macros
%D   {appendtoks,prependtoks,appendtoksonce,prependtoksonce,
%D    doifintokselse,flushtoks,dotoks}
%D
%D We use \TOKENLISTS\ sparsely within \CONTEXT, because the
%D comma separated lists are more suitable for the user
%D interface. Nevertheless we have:
%D
%D \starttyping
%D (\doglobal) \appendtoks ... \to\tokenlist
%D (\doglobal) \prependtoks ... \to\tokenlist
%D (\doglobal) \flushtoks\tokenlist
%D             \dotoks\tokenlist
%D \stoptyping
%D
%D Er worden eerst enkele klad||registers gedefinieerd. These
%D macros are clones of the ones implemented in page~378 of
%D Knuth's \TeX book.
%D
%D A simple implementation, one that does not handle braces
%D at the outer level, is:
%D
%D \starttyping
%D \def\appendtoks#1\to#2%
%D   {\scratchtoks={#1}%
%D    \expanded{\dodoglobal\noexpand#2{\the#2\the\scratchtoks}}}
%D
%D \def\prependtoks#1\to#2%
%D   {\scratchtoks={#1}%
%D    \expanded{\dodoglobal\noexpand#2{\the\scratchtoks\the#2}}}
%D \stoptyping
%D
%D But here we prefer:

\newtoks\@@scratchtoks

% before we had the once only alternatives, we had:
%
% \def\appendtoks {\doappendtoks \relax}
% \def\prependtoks{\doprependtoks\relax}
%
% \long\def\doappendtoks#1\to#2%
%   {\@@scratchtoks\@EA{\gobbleoneargument#1}%
%    \expanded{\dodoglobal\noexpand#2{\the#2\the\@@scratchtoks}}}
%
% \long\def\doprependtoks#1\to#2%
%   {\@@scratchtoks\@EA{\gobbleoneargument#1}%
%    \expanded{\dodoglobal\noexpand#2{\the\@@scratchtoks\the#2}}}

\def\appendtoks     {\doappendtoks     \relax}
\def\prependtoks    {\doprependtoks    \relax}
\def\appendtoksonce {\doappendtoksonce \relax}
\def\prependtoksonce{\doprependtoksonce\relax}

% \def\dodoappendtoks#1%
%   {\expanded{\dodoglobal\noexpand#1{\the#1\the\@@scratchtoks}}}
%
% \def\dodoprependtoks#1%
%   {\expanded{\dodoglobal\noexpand#1{\the\@@scratchtoks\the#1}}}
%
% \long\def\doappendtoks#1\to%
%   {\@@scratchtoks\@EA{\gobbleoneargument#1}\dodoappendtoks}
%
% \long\def\doprependtoks#1\to%
%   {\@@scratchtoks\@EA{\gobbleoneargument#1}\dodoprependtoks}
%
% \long\def\doappendtoksonce#1\to#2%
%   {\@@scratchtoks\@EA{\gobbleoneargument#1}%
%    \doifintokselse\@@scratchtoks{#2}{}{\dodoappendtoks{#2}}}
%
% \long\def\doprependtoksonce#1\to#2%
%   {\@@scratchtoks\@EA{\gobbleoneargument#1}%
%    \doifintokselse\@@scratchtoks{#2}{}{\dodoprependtoks{#2}}}
%
% A slightly (but in the case of large arguments
% significantly) faster alternative is given below:

\newtoks\@@toks

\def\dodoappendtoks
  {\dodoglobal\@@toks\@EAEAEA{\@EA\the\@EA\@@toks\the\@@scratchtoks}}

\def\dodoprependtoks
  {\dodoglobal\@@toks\@EAEAEA{\@EA\the\@EA\@@scratchtoks\the\@@toks}}

\long\def\doappendtoks#1\to#2%
  {\def\@@toks{#2}%
   \@@scratchtoks\@EA{\gobbleoneargument#1}\dodoappendtoks}

\long\def\doprependtoks#1\to#2%
  {\def\@@toks{#2}%
   \@@scratchtoks\@EA{\gobbleoneargument#1}\dodoprependtoks}

\long\def\doappendtoksonce#1\to#2%
  {\def\@@toks{#2}%
   \@@scratchtoks\@EA{\gobbleoneargument#1}%
   \doifintokselse\@@scratchtoks\@@toks\donothing\dodoappendtoks}

\long\def\doprependtoksonce#1\to#2%
  {\def\@@toks{#2}%
   \@@scratchtoks\@EA{\gobbleoneargument#1}%
   \doifintokselse\@@scratchtoks\@@toks\donothing\dodoprependtoks}

%D The test macro:
%D
%D \starttyping
%D \def\doifintokselse#1#2% #1 en #2 zijn toks
%D   {\edef\!!stringa{\the#1}\convertcommand\!!stringa\to\asciia
%D    \edef\!!stringb{\the#2}\convertcommand\!!stringb\to\asciib
%D    \doifinstringelse\asciia\asciib}
%D \stoptyping
%D
%D Better:
%D
%D \starttyping
%D \def\doifintokselse#1#2% #1 en #2 zijn toks
%D   {\edef\!!stringa{\the#1}\convertcommand\!!stringa\to\asciia
%D    \edef\!!stringb{\the#2}\convertcommand\!!stringb\to\asciib
%D    \doifstringinstringelse\asciia\asciib}
%D \stoptyping
%D
%D Even better:

\beginETEX

  \def\doifintokselse#1#2% #1 en #2 zijn toks
    {\@EA\convertargument\the#1\to\asciia
     \@EA\convertargument\the#2\to\asciib
     \doifstringinstringelse\asciia\asciib}

\endETEX

\beginTEX

  \def\doifintokselse#1#2% #1 en #2 zijn toks
    {\edef\asciia{\the#1}\convertcommand\asciia\to\asciia
     \edef\asciib{\the#2}\convertcommand\asciib\to\asciib
     \doifstringinstringelse\asciia\asciib}

\endTEX

%D Also:

\def\appendetoks #1\to{\expanded{\appendtoks #1}\to}
\def\prependetoks#1\to{\expanded{\prependtoks#1}\to}

%D Hm.

\def\flushtoks#1% nb: can reassing to #1 again, hence the indirectness
  {\@@scratchtoks#1\relax
   \dodoglobal#1\emptytoks
   \the\@@scratchtoks\relax}

\let\dotoks\the

%D \macros
%D   {makecounter,pluscounter,minuscounter,
%D    resetcounter,setcounter,countervalue}
%D
%D Declaring, setting and resetting \COUNTERS\ can be doen
%D with the next set of commands.
%D
%D \starttyping
%D \makecounter   {name}
%D \pluscounter   {name}
%D \minuscounter  {name}
%D \resetcounter  {name}
%D \setcounter    {name} {value}
%D \countervalue  {name}
%D \stoptyping
%D
%D We prefer the use of global counters. This means that we
%D have to load \PLAIN\ \TEX\ in a bit different way:
%D
%D \starttyping
%D \let\oldouter=\outer
%D \let\outer=\relax
%D \input plain.tex
%D \let\outer=\oldouter
%D
%D \def\newcount%
%D   {\alloc@0\count\countdef\insc@unt}
%D \stoptyping
%D
%D First we show a solution in which we use real \COUNTERS.
%D Apart from some expansion, nothing special is done.
%D
%D \starttyping
%D \def\makecounter#1%
%D   {\expandafter\newcount\csname#1\endcsname}
%D
%D \def\pluscounter#1%
%D   {\global\advance\csname#1\endcsname by 1 }
%D
%D \def\minuscounter#1%
%D   {\global\advance\csname#1\endcsname by -1 }
%D
%D \def\resetcounter#1%
%D   {\expandafter\global\csname#1\endcsname=0 }
%D
%D \def\setcounter#1#2%
%D   {\expandafter\global\csname#1\endcsname=#2 }
%D
%D \def\countervalue#1%
%D   {\the\getvalue{#1}}
%D \stoptyping
%D
%D Because these macros are already an indirect way of working
%D with counters, there is no harm in using pseudo \COUNTERS\
%D here:

\def\makecounter#1%
  {\letgvalue{#1}\zerocountervalue} % see earlier

% \def\countervalue#1%
%   {\getvalue{#1}}

\let\countervalue\getvalue

\def\pluscounter#1%
  {\scratchcounter\getvalue{#1}%
   \advance\scratchcounter \plusone
   \setxvalue{#1}{\the\scratchcounter}}

\def\minuscounter#1%
  {\scratchcounter\getvalue{#1}%
   \advance\scratchcounter \minusone
   \setxvalue{#1}{\the\scratchcounter}}

\def\resetcounter#1%
  {\letgvalue{#1}\zerocountervalue}

\def\setcounter#1#2% or: \setxvalue{#1}{\number#2}
  {\scratchcounter#2%
   \setxvalue{#1}{\the\scratchcounter}}

\def\incrementcounter#1#2% #1 name #2 value
   {\setxvalue{#1}{\the\numexpr\csname#1\endcsname+#2\relax}}

\def\decrementcounter#1#2% #1 name #2 value
   {\setxvalue{#1}{\the\numexpr\csname#1\endcsname-#2\relax}}

%D \macros
%D   {savecounter,restorecounter}
%D
%D These two commands can be used to save and restore counter
%D values. Only one level is saved.

\def\savecounter#1%
  {{\scratchcounter\getvalue {#1}\setxvalue{!#1}{\the\scratchcounter}}}

\def\restorecounter#1%
  {{\scratchcounter\getvalue{!#1}\setxvalue {#1}{\the\scratchcounter}}}

% == {\setxvalue{#1}{\getvalue{!#1}}}

%D The next \ETEX\ based solution is some 15\% faster, which
%D goes unnoticed in any normal run, simply because these
%D macros are not used milions of times.

\beginETEX \numexpr

\def\makecounter#1%
  {\global\@EA\let\csname#1\endcsname\zerocountervalue} % see earlier

\def\countervalue#1%
  {\ifcsname#1\endcsname\csname#1\endcsname\fi}

\def\pluscounter#1%
  {\@EA\xdef\csname#1\endcsname{\the\numexpr\csname#1\endcsname+\plusone\relax}}

\def\minuscounter#1%
  {\@EA\xdef\csname#1\endcsname{\the\numexpr\csname#1\endcsname-\plusone\relax}}

\def\resetcounter#1%
  {\global\@EA\let\csname#1\endcsname\zerocountervalue}

\def\setcounter#1#2%
  {\@EA\xdef\csname#1\endcsname{\the\numexpr#2\relax}}

\def\savecounter#1%
  {\@EA\xdef\csname !#1\endcsname{\the\numexpr\csname#1\endcsname\relax}}

\def\restorecounter#1%
  {\@EA\xdef\csname#1\endcsname{\the\numexpr\csname !#1\endcsname\relax}}

\endETEX

%D \macros
%D   {beforesplitstring,aftersplitstring}
%D
%D These both commands split a string at a given point in two
%D parts, so \type{x.y} becomes \type{x} or \type{y}.
%D
%D \starttyping
%D \beforesplitstring test.tex\at.\to\filename
%D \aftersplitstring  test.tex\at.\to\extension
%D \stoptyping
%D
%D The first routine looks (and is indeed) a bit simpler than
%D the second one. The alternative looking more or less like
%D the first one did not always give the results we needed.
%D Both implementations show some insight in the manipulation
%D of arguments.

\def\beforesplitstring#1\at#2\to#3%
  {\def\dosplitstring##1#2##2#2##3\\%
     {\def#3{##1}}%
   \@EA\dosplitstring#1#2#2\\}

\def\aftersplitstring#1\at#2\to#3%
  {\def\dosplitstring##1#2##2@@@##3\\%
     {\def#3{##2}}%
   \@EA\dosplitstring#1@@@#2@@@\\}

%D \macros
%D   {splitstring,greedysplitstring}
%D
%D A bonus macro.

\def\splitstring#1\at#2\to#3\and#4%
  {\def\dosplitstring##1#2##2\empty\empty\empty##3\\%
     {\def#3{##1}%
      \def\dosplitstring{##3}%
      \ifx\dosplitstring\empty
        \let#4\empty
      \else
        \def#4{##2}%
      \fi}%
   \@EA\dosplitstring#1\empty\empty\empty#2\empty\empty\empty\\}

% Ok, but not for all cases:
%
% \def\greedysplitstring#1\at#2\to#3\and#4%
%   {\edef\asciib{#1}%
%    \let\asciic\asciib
%    \let#3\empty
%    \let#4\empty
%    \doloop
%      {\expandafter\splitstring\asciib\at#2\to\asciia\and\asciib
%       \ifx\asciib\empty
%         \exitloop
%       \else
%         \edef#3{\ifx#3\empty\else#3#2\fi\asciia}%
%         \let#4\asciib
%       \fi}%
%   \ifx#3\empty\let#3\asciic\fi}
%
% The next one is some 25\% faster, but it hardly matters because
% we seldom use this macro.
%
% \def\greedysplitstring#1\at#2\to#3\and#4%
%   {\edef\asciib{#1}%
%    \let\asciic\asciib
%    \let#3\empty
%    \let#4\empty
%    \def\dogreedysplitstring
%      {\expandafter\splitstring\asciib\at#2\to\asciia\and\asciib
%       \ifx\asciib\empty
%         \expandafter\dogreedysplitstring
%       \else
%         \edef#3{\ifx#3\empty\else#3#2\fi\asciia}%
%         \let#4\asciib
%       \fi}%
%   \dogreedysplitstring
%   \ifx#3\empty\let#3\asciic\fi}
%
% The better alternative:

\def\greedysplitstring#1\at#2\to#3\and#4%
  {\edef\asciib{#1}%
   \let\asciic\asciib
   \let#3\empty
   \let#4\empty
   \doloop
     {\expandafter\splitstring\asciib\at#2\to\asciia\and\asciib
      \ifx\asciib\empty
        \exitloop
      \else
        % not \edef#3{\ifx#3\empty\else#3#2\fi\asciia} else
        % /root/path fails because then #3==empty
        \edef#3{\ifcase\recurselevel\or\else#3#2\fi\asciia}%
        \let#4\asciib
      \fi}%
  \ifx#3\empty\let#3\asciic\fi}

%D \macros
%D   {beforetestandsplitstring,
%D    aftertestandsplitstring,
%D    testandsplitstring}
%D
%D The next alternatives are for Simon Pepping. This time
%D the result is empty when no split is done.

% \def\beforetestandsplitstring#1\at#2\to#3%
%   {\def\dosplitstring##1#2##2#2##3\\{\doifelsenothing
%      {##3}{\let#3\empty}{\def#3{##1}}}%
%    \@EA\dosplitstring#1#2#2\\}
%
% \def\aftertestandsplitstring#1\at#2\to#3%
%   {\def\dosplitstring ##1#2##2@@@##3\\{\doifelsenothing
%      {##3}{\let#3\empty}{\def#3{##2}}}%
%    \@EA\dosplitstring #1@@@#2@@@\\}
%
% \def\testandsplitstring#1\at#2\to#3\and#4%
%   {\def\dosplitstring##1#2##2#2##3\\{\doifelsenothing
%      {##3}{\let#3\empty\let#4\empty}{\def#3{##1}\def#4{##2}}}%
%    \@EA\dosplitstring#1#2#2\\}
%
% faster:

\def\beforetestandsplitstring#1\at#2\to#3%
  {\def\dosplitstring##1#2##2#2##3##4\\%
     {\ifx##3\empty\let#3\empty\else\def#3{##1}\fi}%
   \@EA\dosplitstring#1#2#2\empty\\}

\def\aftertestandsplitstring#1\at#2\to#3%
  {\def\dosplitstring ##1#2##2@@@##3##4\\%
     {\ifx##3\empty\let#3\empty\else\def#3{##2}\fi}%
   \@EA\dosplitstring #1@@@#2@@@\empty\\}

\def\testandsplitstring#1\at#2\to#3\and#4%
  {\def\dosplitstring##1#2##2#2##3##4\\%
     {\ifx##3\empty\let#3\empty\let#4\empty\else\def#3{##1}\def#4{##2}\fi}%
   \@EA\dosplitstring#1#2#2\empty\\}

%D \macros
%D   {removesubstring}
%D
%D A first application of the two routines defined above is:
%D
%D \starttyping
%D \removesubstring-\from first-last\to\nothyphenated
%D \stoptyping
%D
%D Which in terms of \TEX\ looks like:

%\def\removesubstring#1\from#2\to#3%
%  {\doifinstringelse{#1}{#2}
%     {\beforesplitstring#2\at#1\to\!!stringa
%      \aftersplitstring #2\at#1\to\!!stringb
%      \edef#3{\!!stringa\!!stringb}%
%      \removesubstring#1\from#3\to#3}
%     {}}

\def\removesubstring#1\from#2\to#3%
  {\splitstring#2\to\!!stringa\and\!!stringb
   \dodoglobal#3{\!!stringa\!!stringb}}

%D \macros
%D   {appendtocommalist,prependtocommalist,
%D    addtocommalist,removefromcommalist}
%D
%D When working with comma separated lists, one sooner or
%D later want the tools to append or remove items from such a
%D list. When we add an item, we first check if it's already
%D there. This means that every item in the list is unique.
%D
%D \starttyping
%D \addtocommalist      {alfa}  \name
%D \addtocommalist      {beta}  \name
%D \addtocommalist      {gamma} \name
%D \removefromcommalist {beta}  \name
%D \stoptyping
%D
%D These commands can be prefixed with \type{\doglobal}. The
%D implementation of the second command is more complecated,
%D because we have to take leading spaces into account. Keep in
%D mind that users may provide lists with spaces after the
%D commas. When one item is left, we also have to get rid of
%D trailing spaces.
%D
%D \starttyping
%D \def\words{alfa, beta, gamma, delta}
%D \def\words{alfa,beta,gamma,delta}
%D \stoptyping
%D
%D Removing an item takes more time than adding one.
%D
%D A fast appending alternative, without any testing, is
%D also provided:
%D
%D \starttyping
%D \appendtocommalist  {something} \name
%D \prependtocommalist {something} \name
%D \stoptyping
%D
%D This can be implemented as follows:
%D
%D \starttyping
%D \def\appendtocommalist#1#2%
%D   {\ifx#2\empty
%D      \dodoglobal\edef#2{#1}%
%D    \else % no test on empty
%D      \dodoglobal\edef#2{#2,#1}%
%D    \fi}
%D
%D \def\prependtocommalist#1#2%
%D   {\ifx#2\empty
%D      \dodoglobal\edef#2{#1}%
%D    \else % no test on empty
%D      \dodoglobal\edef#2{#1,#2}%
%D    \fi}
%D \stoptyping
%D
%D The faster alternatives are:

\def\appendtocommalist#1#2%
  {\dodoglobal\edef#2{\ifx#2\empty\else#2,\fi#1}}

\def\prependtocommalist#1#2%
  {\dodoglobal\edef#2{#1\ifx#2\empty\else,#2\fi}}

%D The old ones are:
%D
%D \starttyping
%D \def\addtocommalist#1#2%
%D   {\ifx#2\empty
%D      \dodoglobal\edef#2{#1}%
%D    \else
%D      \edef\!!stringa{#2,,}%
%D      \beforesplitstring#2\at,,\to#2\relax
%D      \ExpandBothAfter\doifinsetelse{#1}{#2}
%D        {\resetglobal}
%D        {\dodoglobal\edef#2{#2,#1}}%
%D    \fi}
%D
%D \def\pretocommalist#1#2%
%D   {\ifx#2\empty
%D      \dodoglobal\edef#2{#1}%
%D    \else
%D      \edef\!!stringa{#2,,}%
%D      \beforesplitstring#2\at,,\to#2\relax
%D      \ExpandBothAfter\doifinsetelse{#1}{#2}
%D        {\resetglobal}
%D        {\dodoglobal\edef#2{#1,#2}}%
%D    \fi}
%D
%D \def\doremovefromcommalist#1#2#3% nog \doglobal
%D   {\edef\!!stringa{,,#3,,}%
%D    \beforesplitstring\!!stringa\at,#1#2,\to\!!stringb
%D    \aftersplitstring\!!stringa\at,#1#2,\to\!!stringc
%D    \edef#3{\!!stringb,\!!stringc}%
%D    \aftersplitstring#3\at,,\to#3\relax
%D    \beforesplitstring#3\at,,\to#3}
%D
%D \def\removefromcommalist#1#2%
%D   {\doremovefromcommalist{ }{#1}{#2}%
%D    \doremovefromcommalist{}{#1}{#2}%
%D    \dofrontstrip#2%
%D    \dodoglobal\edef#2{#2}}
%D \stoptyping
%D
%D Significantly faster (especially for longer lists):

\def\addtocommalist#1#2% {item} \cs
  {\rawdoifinsetelse{#1}#2\resetglobal
     {\dodoglobal\edef#2{\ifx#2\empty\else#2,\fi#1}}}

\def\pretocommalist#1#2% {item} \cs
  {\rawdoifinsetelse{#1}#2\resetglobal
     {\dodoglobal\edef#2{#1\ifx#2\empty\else,#2\fi}}}

\def\robustdoifinsetelse#1#2%
  {\expanded{\convertargument#1}\to\!!stringa
   \expanded{\convertargument#2}\to\!!stringb
   \rawdoifinsetelse\!!stringa\!!stringb}

\def\robustaddtocommalist#1#2% {item} \cs
  {\robustdoifinsetelse{#1}#2\resetglobal
     {\dodoglobal\edef#2{\ifx#2\empty\else#2,\fi#1}}}

\def\robustpretocommalist#1#2% {item} \cs
  {\robustdoifinsetelse{#1}#2\resetglobal
     {\dodoglobal\edef#2{#1\ifx#2\empty\else,#2\fi}}}

\def\xsplitstring#1#2% \cs {str}
  {\def\dosplitstring##1,#2,##2,#2,##3\\%
     {\edef\!!stringa{\bcleanedupcommalist##1\empty\empty\relax}%
      \edef\!!stringb{\acleanedupcommalist##2,,\relax}}%
   \@EA\dosplitstring\@EA,#1,,#2,,#2,\\}

\def\bcleanedupcommalist#1#2#3\relax{\if#1,\else#1\fi\if#2,\else#2\fi#3}
\def\bcleanedupcommalist#1#2\relax{\if#1,\else#1\fi#2}
\def\acleanedupcommalist#1,,#2\relax{#1}

% \def\removefromcommalist#1#2%
%   {\expanded{\xsplitstring\noexpand#2{#1}}%
%    \dodoglobal\edef#2%
%      {\ifx\!!stringa\empty
%         \!!stringb
%       \else
%         \@EA\acleanedupcommalist\!!stringa,,\relax
%         \ifx\!!stringb\empty\else,\!!stringb\fi
%       \fi}}

\def\removefromcommalist#1#2%
  {\rawdoifinsetelse{#1}#2%
     {\expanded{\xsplitstring\noexpand#2{#1}}%
      \dodoglobal\edef#2%
        {\ifx\!!stringa\empty
           \!!stringb
         \else
           \!!stringa\ifx\!!stringb\empty\else,\!!stringb\fi
         \fi}}
     \resetglobal}

%D \macros
%D   {substituteincommalist}
%D
%D Slow but seldom used, so for the moment we stick to this
%D implementation.
%D
%D \starttyping
%D \substituteincommalist{old}{new}{list}
%D \stoptyping

\def\substituteincommalist#1#2#3% old, new, list (slooow)
  {\edef\!!stringb{#1}%
   \edef\!!stringd{#2}%
   \let\!!stringa#3%
   \let#3\empty
   \def\dosubstituteincommalist##1%
     {\edef\!!stringc{##1}%
      \ifx\!!stringb\!!stringc
        \ifx\!!stringd\empty\else
          \edef#3{#3\ifx#3\empty\else,\fi\!!stringd}%
        \fi
        \def\docommand####1{\edef#3{#3,####1}}%
      \else
        \edef#3{#3\ifx#3\empty\else,\fi##1}%
      \fi}%
   \@EA\rawprocesscommacommand\@EA[\!!stringa]\dosubstituteincommalist}

%D A not so useful macro:

\def\dodofrontstrip[#1#2]#3%
  {\ifx#1\space
     \def#3{#2}%
   \else
     \def#3{#1#2}%
   \fi}

\def\dofrontstrip#1%
  {\edef\!!stringa{#1}%
   \ifx\!!stringa\empty \else
     \@EA\dodofrontstrip\@EA[#1]#1%
   \fi}

%D \macros
%D   {replaceincommalist}
%D
%D The next macro can be used to replace an indexed element
%D in a commalist:
%D
%D \starttyping
%D \replaceincommalist\MyList{2}
%D \stoptyping
%D
%D Element~2 will be replaced by the current meaning of the macro
%D \type {\newcommalistelement}. The old meaning is saved in
%D \type {\commalistelement}. The replacement honors grouped items,
%D like in:
%D
%D \starttyping
%D \def\MyList{a,b,c,d,e,f}   \replaceincommalist\MyList{3}
%D \def\MyList{a,b,c,d,e,f}   \replaceincommalist\MyList{3}
%D \def\MyList{a,{b,c},d,e,f} \replaceincommalist\MyList{3}
%D \def\MyList{a,b,c,{d,e,f}} \replaceincommalist\MyList{3}
%D \stoptyping

\let\newcommalistelement\empty

\def\replaceincommalist#1#2% #1 = commalistelement #2 = position starts at 1
  {\def\doreplaceincommalist##1%
     {\ifnum\commalistcounter=#2\relax
        \ifx\newcommalistelement\empty\else
          \ifx\newcommalist\empty
            \let\newcommalist\newcommalistelement
          \else
            \@EA\@EA\@EA\def\@EA\@EA\@EA\newcommalist\@EA\@EA\@EA
              {\@EA\newcommalist\@EA,\newcommalistelement}%
          \fi
        \fi
        \def\commalistelement{##1}%
      \else
        \ifx\newcommalist\empty
          \ifx\nexttoken\bgroup % is known -)
            \def\newcommalist{{##1}}%
          \else
            \def\newcommalist{##1}%
          \fi
        \else
          \ifx\nexttoken\bgroup % is known -)
            \@EA\def\@EA\newcommalist\@EA{\newcommalist,{##1}}%
          \else
            \@EA\def\@EA\newcommalist\@EA{\newcommalist,##1}%
          \fi
        \fi
      \fi
      \advance\commalistcounter\plusone}%
   \let\commalistelement\empty
   \let\newcommalist\empty
   \commalistcounter\plusone
   \@EA\processcommalist\@EA[#1]\doreplaceincommalist
   \dodoglobal\let#1\newcommalist}

%D \macros
%D   {globalprocesscommalist}
%D
%D The commalist processing commands are characterized by the
%D fact that the way they handle expansion as well as the fact
%D that they can be nested. This makes them kind of useless for
%D handling comma lists in alignments. In these situations the
%D next macro can be of use.

\def\globalprocesscommaitem#1,%
  {\if]#1\else
     \globalcommacommand{#1}%
     \expandafter\globalprocesscommaitem
   \fi}

\def\globalprocesscommalist[#1]#2%
  {\global\let\globalcommacommand#2%
   \expandafter\globalprocesscommaitem#1,],}

%D \macros
%D   {startprocesscommalist,startprocesscommacommand}
%D
%D Two more:

\long\def\startprocesscommalist[#1]#2\stopprocesscommalist
  {\long\def\currentcommalistcommand##1{\def\currentcommalistitem{##1}#2}%
   \processcommalist[#1]\currentcommalistcommand}

\long\def\startprocesscommacommand[#1]#2\stopprocesscommacommand
  {\long\def\currentcommalistcommand##1{\def\currentcommalistitem{##1}#2}%
   \processcommacommand[#1]\currentcommalistcommand}

%D \macros
%D   {withoutpt,PtToCm,
%D    numberofpoints,dimensiontocount}
%D
%D We can convert point into centimeters with:
%D
%D \starttyping
%D \PtToCm{dimension}
%D \stoptyping

{\catcode`\.=\@@other
 \catcode`\p=\@@other
 \catcode`\t=\@@other
 \gdef\WITHOUTPT#1pt{#1}}

\def\withoutpt#1%
  {\expandafter\WITHOUTPT#1}

%D The capitals are needed because \type{p} and \type{t} have
%D \CATCODE~12, while macronames only permit tokens with the
%D \CATCODE~11. As a result we cannot use the \type{.group}
%D primitives. Those who want to know more about this kind of
%D manipulations, we advice to study the \TEX book in detail.
%D Because this macro does not do any assignment, we can use it
%D in the following way too.

\def\PtToCm#1%
  {\begingroup
   \scratchdimen#1\relax
   \scratchdimen0.0351459804\scratchdimen % 2.54/72.27
   \withoutpt\the\scratchdimen cm%
   \endgroup}

%D We also support:
%D
%D \starttyping
%D \numberofpoints   {dimension}
%D \dimensiontocount {dimension} {\count}
%D \stoptyping
%D
%D Both macros return a rounded number.

% \dimensiontocount{10.49pt}\scratchcounter \the\scratchcounter / \numberofpoints{10.49pt}
% \dimensiontocount{10.51pt}\scratchcounter \the\scratchcounter / \numberofpoints{10.51pt}

\def\dimensiontocount#1#2{#2\numexpr\dimexpr#1\relax/\maxcard\relax}
\def\numberofpoints    #1{\the\numexpr\dimexpr#1\relax/\maxcard\relax}

%D \macros
%D   {swapdimens,swapmacros}
%D
%D Simple but effective are the next two macros. There name
%D exactly states their purpose. The \type{\scratchdimen} and
%D \type{\!!stringa} can only be swapped when being the first
%D argument.

\def\swapdimens#1#2%
  {\scratchdimen #1\redoglobal    #1#2\dodoglobal    #2\scratchdimen}

\def\swapmacros#1#2%
  {\let\!!stringa#1\redoglobal\let#1#2\dodoglobal\let#2\!!stringa}

%D \macros
%D   {pushmacro,popmacro}
%D
%D Premature and a bit of beta, we offer:
%D
%D \starttyping
%D \pushmacro\macro
%D \popmacro\macro
%D \stoptyping
%D
%D Beware: global!

% \def\@s@{@s@}
%
% \beginTEX
%
% \def\globalpushmacro#1% we can use a faster incement here
%   {\@EA\doglobal\@EA\increment\csname\@s@*\string#1\endcsname
%    \global\@EA\let\csname\csname\@s@*\string#1\endcsname*\string#1\endcsname#1}
%
% \def\globalpopmacro#1% \global\let
%   {\global\@EA\let\@EA#1\csname\csname\@s@*\string#1\endcsname*\string#1\endcsname
%    \@EA\doglobal\@EA\decrement\csname\@s@*\string#1\endcsname}
%
% \def\localpushmacro#1% this one can be used to push a value over an \egroup
%   {\@EA\doglobal\@EA\increment\csname\@s@**\string#1\endcsname
%    \global\@EA\let\csname\csname\@s@**\string#1\endcsname**\string#1\endcsname#1}
%
% \def\localpopmacro#1% \local\let
%   {\@EA\let\@EA#1\csname\csname\@s@**\string#1\endcsname**\string#1\endcsname
%    \global\@EA\decrement\csname\@s@**\string#1\endcsname}
%
% \endTEX
%
% \beginETEX \newcount
%
% \def\globalpushmacro#1%
%   {\ifcsname\@s@*\string#1\endcsname \else
%      \@EA\newcount\csname\@s@*\string#1\endcsname
%    \fi
%    \global\advance\csname\@s@*\string#1\endcsname \plusone
%    \global\@EA\let\csname\the\csname\@s@*\string#1\endcsname*\string#1\endcsname#1}
%
% \def\globalpopmacro#1% \global\let
%   {\global\@EA\let\@EA#1\csname\the\csname\@s@*\string#1\endcsname*\string#1\endcsname
%    \global\advance\csname\@s@*\string#1\endcsname \minusone}
%
% \def\localpushmacro#1% this one can be used to push a value over an \egroup
%   {\ifcsname\@s@**\string#1\endcsname \else
%      \@EA\newcount\csname\@s@**\string#1\endcsname
%    \fi
%    \global\advance\csname\@s@**\string#1\endcsname \plusone
%    \global\@EA\let\csname\the\csname\@s@**\string#1\endcsname**\string#1\endcsname#1}
%
% \def\localpopmacro#1% \local\let
%   {\@EA\let\@EA#1\csname\the\csname\@s@**\string#1\endcsname**\string#1\endcsname
%    \global\advance\csname\@s@**\string#1\endcsname \minusone }
%
% \endETEX
%
% some 5% faster (used a lot in typescripts, so ...)

\def\@sl@{@sl@}
\def\@sg@{@sg@}

\let\@@pushedmacro\empty

\beginTEX

\def\globalpushmacro#1% we can use a faster incement here
  {\xdef\@@pushedmacro{\string#1}%
   \@EA\doglobal\@EA\increment\csname\@sg@\@@pushedmacro\endcsname
   \global\@EA\let\csname\csname\@sg@\@@pushedmacro\endcsname\@@pushedmacro\endcsname#1}

\def\globalpopmacro#1%
  {\xdef\@@pushedmacro{\string#1}%
   \global\@EA\let\@EA#1\csname\csname\@sg@\@@pushedmacro\endcsname\@@pushedmacro\endcsname
   \@EA\doglobal\@EA\decrement\csname\@sg@\@@pushedmacro\endcsname}

\def\localpushmacro#1% this one can be used to push a value over an \egroup
  {\xdef\@@pushedmacro{\string#1}%
   \@EA\doglobal\@EA\increment\csname\@sl@\@@pushedmacro\endcsname
   \global\@EA\let\csname\csname\@sl@\@@pushedmacro\endcsname\@@pushedmacro\endcsname#1}

\def\localpopmacro#1%
  {\xdef\@@pushedmacro{\string#1}%
   \@EA\let\@EA#1\csname\csname\@sl@\@@pushedmacro\endcsname\@@pushedmacro\endcsname
   \global\@EA\decrement\csname\@sl@\@@pushedmacro\endcsname}

\endTEX

\beginETEX

\def\globalpushmacro#1%
  {\xdef\@@pushedmacro{\string#1}%
   \ifcsname\@sg@\@@pushedmacro\endcsname \else
     \@EA\newcount\csname\@sg@\@@pushedmacro\endcsname
   \fi
   \global\advance\csname\@sg@\@@pushedmacro\endcsname \plusone
   \global\@EA\let\csname\the\csname\@sg@\@@pushedmacro\endcsname\@@pushedmacro\endcsname#1}

\def\globalpopmacro#1%
  {\xdef\@@pushedmacro{\string#1}%
   \global\@EA\let\@EA#1\csname\the\csname\@sg@\@@pushedmacro\endcsname\@@pushedmacro\endcsname
   \global\advance\csname\@sg@\@@pushedmacro\endcsname \minusone}

\def\localpushmacro#1% this one can be used to push a value over an \egroup
  {\xdef\@@pushedmacro{\string#1}%
   \ifcsname\@sl@\@@pushedmacro\endcsname \else
     \@EA\newcount\csname\@sl@\@@pushedmacro\endcsname
   \fi
   \global\advance\csname\@sl@\@@pushedmacro\endcsname \plusone
   \global\@EA\let\csname\the\csname\@sl@\@@pushedmacro\endcsname\@@pushedmacro\endcsname#1}

\def\localpopmacro#1%
  {\xdef\@@pushedmacro{\string#1}%
   \@EA\let\@EA#1\csname\the\csname\@sl@\@@pushedmacro\endcsname\@@pushedmacro\endcsname
   \global\advance\csname\@sl@\@@pushedmacro\endcsname \minusone }

\endETEX

% \let\pushmacro\globalpushmacro
% \let\popmacro \globalpopmacro

\let\pushmacro\localpushmacro
\let\popmacro \localpopmacro

%D \macros
%D   {setlocalhsize}
%D
%D Sometimes we need to work with the \type{\hsize} that is
%D corrected for indentation and left and right skips. The
%D corrected value is available in \type{\localhsize}, which
%D needs to be calculated with \type{\setlocalhsize} first.
%D
%D \starttyping
%D \setlocalhsize        \hbox to \localhsize{...}
%D \setlocalhsize[-1em]  \hbox to \localhsize{...}
%D \setlocalhsize[.5ex]  \hbox to \localhsize{...}
%D \stoptyping
%D
%D These examples show us that an optional can be used. The
%D value provided is added to \type{\localhsize}.

\newdimen\localhsize

\def\complexsetlocalhsize[#1]% don't change !
  {\localhsize\hsize
   \ifnum\hangafter<\zerocount
     \advance\localhsize\ifdim\hangindent>\zeropoint-\fi\hangindent
   \fi
   \advance\localhsize -\leftskip
   \advance\localhsize -\rightskip
   \advance\localhsize #1\relax}

\def\simplesetlocalhsize
  {\complexsetlocalhsize[\zeropoint]}

\definecomplexorsimple\setlocalhsize

%D \macros
%D   {doifvalue,doifnotvalue,doifelsevalue,
%D    doifnothing,doifsomething,doifelsenothing,
%D    doifvaluenothing,doifvaluesomething,doifelsevaluenothing}
%D
%D These long named \type{\if} commands can be used to access
%D macros (or variables) that are normally accessed by using
%D \type{\getvalue}. Using these alternatives safes us three
%D tokens per call. Anyone familiar with the not||values
%D ones, can derive their meaning from the definitions.

           \def\doifvalue#1{\doif    {\csname#1\endcsname}}
        \def\doifnotvalue#1{\doifnot {\csname#1\endcsname}}
       \def\doifelsevalue#1{\doifelse{\csname#1\endcsname}}

         \def\doifnothing#1{\doif    {#1}{}}
       \def\doifsomething#1{\doifnot {#1}{}}
     \def\doifelsenothing#1{\doifelse{#1}{}}

    \def\doifvaluenothing#1{\doif    {\csname#1\endcsname}{}}
  \def\doifvaluesomething#1{\doifnot {\csname#1\endcsname}{}}
\def\doifelsevaluenothing#1{\doifelse{\csname#1\endcsname}{}}

%D Faster but spoiling inheritance (copying parameters):
%D
%D \starttyping
%D \def\doifelsevaluesomething#1#2#3%
%D   {\expandafter\ifx\csname#1\endcsname\empty#3\else#2\fi}
%D
%D \def\doifvaluesomething#1#2%
%D   {\expandafter\ifx\csname#1\endcsname\empty\else#2\fi}
%D
%D \def\doifvaluenothing#1#2%
%D   {\expandafter\ifx\csname#1\endcsname\empty#2\fi}
%D \stoptyping
%D
%D Slightly more efficient:

    \def\doifnothing{\doif    \empty}
  \def\doifsomething{\doifnot \empty}
\def\doifelsenothing{\doifelse\empty}

%D The somewhat faster alternatives are:

\long\def\doifvalue#1#2%
  {\edef\!!stringa{\csname#1\endcsname}\edef\!!stringb{#2}%
   \ifx\!!stringa\!!stringb
     \expandafter\firstofoneargument
   \else
     \expandafter\gobbleoneargument
   \fi}

\long\def\doifnotvalue#1#2%
  {\edef\!!stringa{\csname#1\endcsname}\edef\!!stringb{#2}%
   \ifx\!!stringa\!!stringb
     \expandafter\gobbleoneargument
   \else
     \expandafter\firstofoneargument
   \fi}

\long\def\doifelsevalue#1#2%
  {\edef\!!stringa{\csname#1\endcsname}\edef\!!stringb{#2}%
   \ifx\!!stringa\!!stringb
     \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

\long\def\doifnothing#1%
  {\edef\!!stringa{#1}%
   \ifx\!!stringa\empty
     \expandafter\firstofoneargument
   \else
     \expandafter\gobbleoneargument
   \fi}

\long\def\doifsomething#1%
  {\edef\!!stringa{#1}%
   \ifx\!!stringa\empty
     \expandafter\gobbleoneargument
   \else
     \expandafter\firstofoneargument
   \fi}

\long\def\doifelsenothing#1%
  {\edef\!!stringa{#1}%
   \ifx\!!stringa\empty
     \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

\long\def\doifsomethingelse#1%
  {\edef\!!stringa{#1}%
   \ifx\!!stringa\empty
     \expandafter\secondoftwoarguments
   \else
     \expandafter\firstoftwoarguments
   \fi}

\long\def\doifvaluenothing#1%
  {\edef\!!stringa{\csname#1\endcsname}%
   \ifx\!!stringa\empty
     \expandafter\firstofoneargument
   \else
     \expandafter\gobbleoneargument
   \fi}

\long\def\doifvaluesomething#1%
  {\edef\!!stringa{\csname#1\endcsname}%
   \ifx\!!stringa\empty
     \expandafter\gobbleoneargument
   \else
     \expandafter\firstofoneargument
   \fi}

\long\def\doifelsevaluenothing#1%
  {\edef\!!stringa{\csname#1\endcsname}%
   \ifx\!!stringa\empty
     \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

%D \macros
%D   {doifemptyelsevalue, doifemptyvalue, doifnotemptyvalue}
%D
%D Also handy:

\def\doifemptyelsevalue#1%
  {\@EA\ifx\csname#1\endcsname\empty
     \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

\def\doifemptyvalue#1%
  {\@EA\ifx\csname#1\endcsname\empty
     \expandafter\firstofoneargument
   \else
     \expandafter\gobbleoneargument
   \fi}

\def\doifnotemptyvalue#1%
  {\@EA\ifx\csname#1\endcsname\empty
     \expandafter\gobbleoneargument
   \else
     \expandafter\firstofoneargument
   \fi}

%D \macros
%D   {doifallcommonelse}
%D
%D A complete match of two sets can be tested with
%D \type {\doifallcommonelse}, where the first two
%D arguments are sets.

%\def\doifallcommonelse#1#2#3#4%
%  {\def\p!docommoncheck##1%
%     {\doifnotinset{##1}{#2}{\donefalse}%
%      \ifdone\else\quitcommalist\fi}%
%   \donetrue
%   \processcommalist[#1]\p!docommoncheck
%   \ifdone#3\else#4\fi}

\def\@@doifallcommonelse#1#2#3#4% slow
  {\def\p!docommoncheck##1%
     {\doifnotinset{##1}{#4}\donefalse
      \ifdone\else\expandafter\quitcommalist\fi}%
   \donetrue
   \processcommalist[#3]\p!docommoncheck
   \ifdone\expandafter#1\else\expandafter#2\fi}

\def\doifallcommonelse
  {\@@doifallcommonelse\firstoftwoarguments\secondoftwoarguments}

\def\doifallcommon
  {\@@doifallcommonelse\firstofonearguments\gobbleoneargument}

\def\doifnotallcommon
  {\@@doifallcommonelse\gobbleoneargument\firstofonearguments}

%D \macros
%D   {DOIF,DOIFELSE,DOIFNOT}
%D
%D \TEX\ is case sensitive. When comparing arguments, this
%D feature sometimes is less desirable, for instance when we
%D compare filenames. The next three alternatives upcase their
%D arguments before comparing them.
%D
%D \starttyping
%D \DOIF     {string1} {string2} {...}
%D \DOIFNOT  {string1} {string2} {...}
%D \DOIFELSE {string1} {string2} {then ...}{else ...}
%D \stoptyping
%D
%D We have to use a two||step implementation, because the
%D expansion has to take place outside \type{\uppercase}.

\def\p!DOIF#1#2%
  {\uppercase{\ifinstringelse{$#1$}{$#2$}}%
     \expandafter\firstofoneargument
   \else
     \expandafter\gobbleoneargument
   \fi}

\def\p!DOIFNOT#1#2%
  {\uppercase{\ifinstringelse{$#1$}{$#2$}}%
     \expandafter\gobbleoneargument
   \else
     \expandafter\firstofoneargument
   \fi}

\def\p!DOIFELSE#1#2%
  {\uppercase{\ifinstringelse{$#1$}{$#2$}}%
     \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

\def\p!DOIFINSTRINGELSE#1#2%
  {\uppercase{\ifinstringelse{#1}{#2}}%
     \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

\def\DOIF             {\ExpandBothAfter\p!DOIF}
\def\DOIFNOT          {\ExpandBothAfter\p!DOIFNOT}
\def\DOIFELSE         {\ExpandBothAfter\p!DOIFELSE}
\def\DOIFINSTRINGELSE {\ExpandBothAfter\p!DOIFINSTRINGELSE}

%D \macros
%D   {dosingleargumentwithset,
%D    dodoubleargumentwithset,dodoubleemptywithset,
%D    dotripleargumentwithset,dotripleemptywithset}
%D
%D These maybe too mysterious macros enable us to handle more
%D than one setup at once.
%D
%D \starttyping
%D \dosingleargumentwithset \command[#1]
%D \dodoubleargumentwithset \command[#1][#2]
%D \dotripleargumentwithset \command[#1][#2][#3]
%D \dodoubleemptywithset    \command[#1][#2]
%D \dotripleemptywithset    \command[#1][#2][#3]
%D \stoptyping
%D
%D The first macro calls \type{\command[##1]} for each string
%D in the set~\type{#1}. The second one calls for
%D \type{\commando[##1][#2]} and the third, well one may guess.
%D These commands support constructions like:
%D
%D \starttyping
%D \def\dodefinesomething[#1][#2]%
%D   {\getparameters[\??xx#1][#2]}
%D
%D \def\definesomething%
%D   {\dodoubleargumentwithset\dodefinesomething}
%D \stoptyping
%D
%D Which accepts calls like:
%D
%D \starttyping
%D \definesomething[alfa,beta,...][variable=...,...]
%D \stoptyping
%D
%D Now a whole bunch of variables like \type{\@@xxalfavariable}
%D and \type{\@@xxbetavariable} is defined.

\def\dodoublewithset#1#2%
  {\def\dododoublewithset[##1][##2]%
     {\doifsomething{##1}
        {\def\dodododoublewithset####1{#2[####1][##2]}%
         \processcommalist[##1]\dodododoublewithset}}%
   #1\dododoublewithset}

\def\dodoubleemptywithset   {\dodoublewithset\dodoubleempty}
\def\dodoubleargumentwithset{\dodoublewithset\dodoubleargument}

\def\dotriplewithset#1#2%
  {\def\dodotriplewithset[##1][##2][##3]%
     {\doifsomething{##1}
        {\def\dododotriplewithset####1{#2[####1][##2][##3]}%
         \processcommalist[##1]\dododotriplewithset}}%
   #1\dodotriplewithset}

\def\dotripleemptywithset   {\dotriplewithset\dotripleempty}
\def\dotripleargumentwithset{\dotriplewithset\dotripleargument}

%D \macros
%D   {stripcharacters,stripspaces}
%D
%D The next command was needed first when we implemented
%D the \CONTEXT\ interactivity macros. When we use labeled
%D destinations, we often cannot use all the characters we
%D want. We therefore strip some of the troublemakers, like
%D spaces, from the labels before we write them to the
%D \DVI||file, which passes them to for instance a PostScript
%D file.
%D
%D \starttyping
%D \stripspaces\from\one\to\two
%D \stoptyping
%D
%D Both the old string \type{\one} and the new one \type{\two}
%D are expanded. This command is a special case of:
%D
%D \starttyping
%D \stripcharacter\char\from\one\to\two
%D \stoptyping
%D
%D As we can see below, spaces following a control sequence are
%D to enclosed in \type{{}}.

% keep this one:
%
% \def\stripcharacter#1\from#2\to#3%
%   {\def\dostripcharacter##1#1##2\end
%      {\edef\!!strippedstring{\!!strippedstring##1}%
%       \doifnotempty{##2}{\dostripcharacter##2\end}}%
%    \let\!!strippedstring\empty
%    \edef\!!stringa{#2}%
%    \@EA\dostripcharacter\!!stringa#1\end
%    \dodoglobal\let#3\!!strippedstring}
%
% the following is better (comes from syst-loc):

\def\stripcharacter#1\from#2\to#3%
  {\def\dostripcharacter##1#1##2\end
     {\edef\!!strippedstring{\!!strippedstring##1}%
      \doifnotempty{##2}{\dostripcharacter##2\end}}%
   \let\!!strippedstring\empty
   \edef\!!stringa{#2}%
   \@EA\dostripcharacter\!!stringa#1\end
   \dodoglobal\let#3\!!strippedstring}

\def\stripspaces\from#1\to#2% will become \unspacestring#1\from#2
  {\stripcharacter{ }\from#1\to#2}

%D \macros
%D   {unspacestring}
%D
%D The next macro does the same but is more compatible with other macros,
%D like \type {\convert...}.

\def\unspacestring#1\to#2%
  {\stripcharacter{ }\from#1\to#2}

%D \macros
%D   {executeifdefined}
%D
%D \CONTEXT\ uses one auxiliary file for all data concerning
%D tables of contents, references, two||pass optimizations,
%D sorted lists etc. This file is loaded as many times as
%D needed. During such a pass we skip the commands thate are of
%D no use at that moment. Because we don't want to come into
%D trouble with undefined auxiliary commands, we call the
%D macros in a way similar to \type{\getvalue}. The next macro
%D take care of such executions and when not defined, gobbles
%D the unwanted arguments.
%D
%D \starttyping
%D \executeifdefined{name}\gobbleoneargument
%D \stoptyping
%D
%D We can of course gobble more arguments using the
%D appropriate gobbling command.

\newif\ifexecuted % general purpose

\def\executeifdefined#1#2%
  {\ifundefined{#1}%
     \def\next{#2}%
   \else
     \def\next{\getvalue{#1}}%
   \fi
   \next}

%D Just for fun I times the next alternative: it was roughly
%D timed about 15\% faster than the default (10+ sec to 9 sec)!

\beginTEX

\def\executeifdefined#1% #2 / never change this one again
  {\ifundefined{#1}%
     \expandafter\secondoftwoarguments
   \else
     \expandafter\firstoftwoarguments
   \fi
   {\csname#1\endcsname}}

\endTEX

\beginETEX

% \def\executeifdefined#1% #2 / never change this one again
%   {\ifcsname#1\endcsname
%      \expandafter\firstoftwoarguments
%    \else
%      \expandafter\secondoftwoarguments
%    \fi
%    {\csname#1\endcsname}}

\def\executeifdefined#1% #2 / never change this one again
  {\ifcsname#1\endcsname
     \csname#1\expandafter\expandafter\expandafter\endcsname\expandafter\gobbleoneargument
   \else
     \expandafter\firstofoneargument
   \fi}

\endETEX

% \letvalue{f }\firstofoneargument \def\executeifdefined#1{\csname\ifcsname#1\endcsname#1\else f \fi\endcsname}

%D This one also has the advantage that it is fully
%D expandable and that it can be used after an assignment.

%D \macros
%D   {executeifdefinedcs}
%D
%D An also fully expandable variant is the following:
%D
%D \starttyping
%D \executeifdefinedcs{a}{b}
%D \stoptyping
%D
%D In dit geval zijn beide argumenten csnames.

\def\executeifdefinedcs#1#2%
  {\csname\ifundefined{#1}#2\else#1\fi\endcsname}

%D We considered an alternative implementation accepting
%D commands directly, like:
%D
%D \starttyping
%D \executeifdefined\name\gobblefivearguments
%D \stoptyping
%D
%D For the moment we don't need this one, so we stick to the
%D faster one.

%D \macros
%D   {executeandforget}
%D
%D The following macros were requested by Simon. Watch the
%D global variant.
%D
%D \starttyping
%D          \executeandforget\SomeCommand
%D \doglobal\executeandforget\AnotherCommand
%D \stoptyping

\def\executeandforget#1%
  {\global\let\@@expanded#1%
   \dodoglobal\let#1\relax
   \@@expanded}

%D \macros
%D   {doifsomespaceelse}
%D
%D The next command checks a string on the presence of a space
%D and executed a command accordingly.
%D
%D \starttyping
%D \doifsomespaceelse {tekst} {then ...} {else ...}
%D \stoptyping
%D
%D We use this command in \CONTEXT\ for determing if an
%D argument must be broken into words when made interactive.
%D Watch the use of \type{\noexpand}.

%D Is this one still needed?

% \long\def\doifsomespaceelse#1#2#3%
%   {\def\p!doifsomespaceelse##1 ##2##3\war%
%      {\if\noexpand##2@#3\else#2\fi}%
%    \p!doifsomespaceelse#1 @ @\war}

\def\p!doifsomespaceelse#1 #2#3\war{\if\noexpand#2@}

\long\def\doifsomespaceelse#1%     % #2#3%
  {\p!doifsomespaceelse#1 @ @\war  % #3\else#2\fi}
     \expandafter\secondoftwoarguments
   \else
     \expandafter\firstoftwoarguments
   \fi}

%D \macros
%D   {adaptdimension,balancedimensions}
%D
%D Again we introduce some macros that are closely related to
%D an interface aspect of \CONTEXT. The first command can be
%D used to adapt a \DIMENSION.
%D
%D \starttyping
%D \adaptdimension {dimension} {value}
%D \stoptyping
%D
%D When the value is preceed by a \type{+} or minus, the
%D dimension is advanced accordingly, otherwise it gets the
%D value.

% \def\doadaptdimension#1#2\\#3\\%
%   {\if#1+%
%      \dodoglobal\advance#3 #1#2\relax
%    \else\if#1-%
%      \dodoglobal\advance#3 #1#2\relax
%    \else
%      \dodoglobal#3=#1#2\relax
%    \fi\fi}
%
% more fuzzy but also more efficient

\def\doadaptdimension#1#2\\#3\\%
  {\if#1+%
     \dodoglobal\advance
   \else\if#1-%
     \dodoglobal\advance
   \else
     \dodoglobal
   \fi\fi
   #3 #1#2\relax}

\def\adaptdimension#1#2%
  {\expandafter\doadaptdimension#2\\#1\\}

%D A second command takes two \DIMENSIONS. Both are adapted,
%D depending on the sign of the given value.
%D maat. This time we take the value as it is, and don't look
%D explicitly at the preceding sign.
%D
%D \starttyping
%D \balancedimensions {dimension 1} {dimension 2} {value}
%D \stoptyping
%D
%D When a positive value is given, the first dimension is
%D incremented, the second ond is decremented. A negative value
%D has the opposite result.

\def\balancedimensions#1#2#3%
  {\scratchdimen#3\relax
   \redoglobal\advance#1  \scratchdimen
   \dodoglobal\advance#2 -\scratchdimen}

%D Both commands can be preceded by \type{\doglobal}. Here we
%D use \type{\redo} first, because \type{\dodo} resets the
%D global character.

%D \macros
%D   {processseparatedlist}
%D
%D Maybe a bit late, but here is a more general version of the
%D \type{\processcommalist} command. This time we don't handle
%D nesting but accept arbitrary seperators.
%D
%D \starttyping
%D \processseparatedlist[list][separator]\command
%D \stoptyping
%D
%D One can think of things like:
%D
%D \starttyping
%D \processseparatedlist[alfa+beta+gamma][+]\message
%D \stoptyping

%D First we show the simple alternative:
%D
%D \starttyping
%D \def\processseparatedlist[#1][#2]#3%
%D   {\def\doprocessseparatedlist##1##2#2%
%D      {\if]##1%
%D         \let\next=\relax
%D       \else\if]##2%
%D         \let\next=\relax
%D       \else\ifx\blankspace##2%
%D         #3{##1}%
%D         \let\next=\doprocessseparatedlist
%D       \else
%D         #3{##1##2}%
%D         \let\next=\doprocessseparatedlist
%D       \fi\fi\fi
%D       \next}%
%D    \doprocessseparatedlist#1#2]#2}
%D \stoptyping
%D
%D However, we want to handle all situations, like:
%D
%D \startbuffer
%D \processseparatedlist[{aap noot}]  [ ]{\def\xxx} \convertcommand\xxx\to\ascii {\tttf\ascii}
%D \processseparatedlist[{aap} {noot}][ ]{\def\xxx} \convertcommand\xxx\to\ascii {\tttf\ascii}
%D \processseparatedlist[aap {noot}]  [ ]{\def\xxx} \convertcommand\xxx\to\ascii {\tttf\ascii}
%D \processseparatedlist[aap noot]    [ ]{\def\xxx} \convertcommand\xxx\to\ascii {\tttf\ascii}
%D \stopbuffer
%D
%D \typebuffer \getbuffer
%D
%D Therefore we smuggle a \type {\relax} in front of the
%D argument, which we remove afterwards.

% \def\doprocessseparatedlist#1]#2[#3]#4%
%   {\def\dodoprocessseparatedlist##1##2#3%
%      {\if]##1%
%         \let\dodoprocessseparatedlist\relax
%       \else\if]##2%
%         \let\dodoprocessseparatedlist\relax
%       \else\ifx\blankspace##2%
%         #4{##1}%
%       \else
%         #4{##1##2}%
%       \fi\fi\fi
%       \dodoprocessseparatedlist}%
%    \@EA\dodoprocessseparatedlist\gobbleoneargument#1#3]#3}

% testcase Vit Zyka:
%
% \def\Do#1{(#1)}
%    1\processseparatedlist[{aap noot}]  [ ]\Do \par
%    2\processseparatedlist[{aap} {noot}][ ]\Do \par
%    3\processseparatedlist[aap {noot}]  [ ]\Do \par
%    4\processseparatedlist[aap noot]    [ ]\Do \par
%    5\processseparatedlist[aap;noot;a noot;noot a; noot a noot][;]\Do \par
%    6\processseparatedlist[][;]\Do \par
%    7\processseparatedlist[;][;]\Do \par

\def\doprocessseparatedlist#1]#2[#3]#4%
   {\def\dodoprocessseparatedlist##1##2#3%
      {\def\!!stringa{##2}% suggested by VZ
       \if]##1%
         \let\dodoprocessseparatedlist\relax
       \else\ifx\blankspace\!!stringa
         #4{##1}%
       \else\if]##2%
         \let\dodoprocessseparatedlist\relax
       \else
         #4{##1##2}%
       \fi\fi\fi
       \dodoprocessseparatedlist}%
    \@EA\dodoprocessseparatedlist\gobbleoneargument#1#3]#3}

\def\processseparatedlist[%
  {\doprocessseparatedlist\relax}

%D \macros
%D   {processlist}
%D
%D An even more general list processing macro is the
%D following one:
%D
%D \starttyping
%D \processlist{beginsym}{endsym}{separator}\docommand list
%D \stoptyping
%D
%D This one supports arbitrary open and close symbols as well
%D as user defined separators.
%D
%D \starttyping
%D \processlist(){=>}\docommand(a=>b=>c=>d)
%D \stoptyping

\long\def\processlist#1#2#3#4% no blank skipping !
  {\def\doprocesslist##1#2%
     {\def\dodoprocesslist####1####2#3%
        {\ifx#2####1%
           \let\dodoprocesslist\relax
         \else\ifx#2####2%
           \let\dodoprocesslist\relax
         \else
           #4{####1####2}%
         \fi\fi
         \dodoprocesslist}%
      \expandafter\dodoprocesslist\gobbleoneargument##1#3#2#3}%
   \def\dodoprocesslist#1%
     {\doprocesslist\relax}%
   \dodoprocesslist}

% %D \macros
% %D   {dohonorgroupedargument}
% %D
% %D The previous macro uses yet another auxiliary macro to
% %D handle the special case.
%
% \def\dohonorgroupedargument#1[%
%   {\doifnextbgroupelse{\dodohonorgroupedargument#1}{#1[}}
%
% \def\dodohonorgroupedargument#1#2%
%   {#1[{{#2}}}

%D \macros
%D   {processassignlist}
%D
%D Is possible to combine an assignment list with one
%D containing keywords. Assignments are treated accordingly,
%D keywords are treated by \type{\command}.
%D
%D \starttyping
%D \processassignlist[...=...,...=...,...]\commando
%D \stoptyping
%D
%D This command can be integrated in \type{\getparameters}, but
%D we decided best not to do so.

\def\processassignlist#1[#2]#3%
  {\def\p!dodogetparameter[##1=##2=##3]%
     {\doifnot{##3}\relax{#3{##1}}}%
   \def\p!dogetparameter##1%
     {\p!dodogetparameter[##1==\relax]}%
   \processcommalist[#2]\p!dogetparameter}

% too ugly
%
% %D \macros
% %D   {DoAfterFi,DoAfterFiFi}
% %D
% %D Sometimes \type{\fi}'s can get into the way. We can reach
% %D over such a troublemaker with:
% %D
% %D \starttyping
% %D \DoAfterFi{some commands}
% %D \DoAfterFiFi{some commands}
% %D \stoptyping
% %D
% %D It saves us a \type{\next} construction. Skipping
% %D \type{\else...\fi} is more tricky, so this one is not
% %D provided.
%
% \def\DoAfterFi#1\fi{\fi#1}
% \def\DoAfterFiFi#1\fi#2\fi{\fi\fi#1}

%D \macros
%D   {untextargument
%D    untexcommand}
%D
%D When manipulating data(bases) and for instance generating
%D index entries, the next three macros can be of help:
%D
%D \starttyping
%D \untextargument{...}\to\name
%D \untexcommand  {...}\to\name
%D \stoptyping
%D
%D They remove braces and backslashes and give us something to
%D sort.

\def\untexsomething
  {\begingroup
   \catcode`\{=\@@ignore
   \catcode`\}=\@@ignore
   \escapechar\minusone
   \dountexsomething}

\long\def\dountexsomething#1#2\to#3%
  {\doglobal#1#2\to\untexedargument
   \endgroup
   \let#3\untexedargument}

\def\untexargument{\untexsomething\convertargument}
\def\untexcommand {\untexsomething\convertcommand}

%D \macros
%D   {ScaledPointsToBigPoints,ScaledPointsToWholeBigPoints}
%D
%D One characteristic of \POSTSCRIPT\ and \PDF\ is that both
%D used big points (\TEX's bp). The next macros convert points
%D and scaled points into big points.
%D
%D \starttyping
%D \ScaledPointsToBigPoints      {number} \target
%D \ScaledPointsToWholeBigPoints {number} \target
%D \stoptyping
%D
%D The magic factor $72/72.27$ can be found in most \TEX\
%D related books.

% \def\ScaledPointsToBigPoints     #1{\PointsToBigPoints     {#1sp}}
% \def\ScaledPointsToWholeBigPoints#1{\PointsToWholeBigPoints{#1sp}}
%
% \def\PointsToBigPoints#1#2%
%   {\scratchdimen#1%
%    \scratchdimen.996264\scratchdimen
%    \edef#2{\withoutpt\the\scratchdimen}}
%
% \def\PointsToWholeBigPoints#1#2%
%   {\scratchdimen#1%
%    \scratchdimen.996264\scratchdimen
%    \scratchcounter\scratchdimen
%    \advance\scratchcounter \medcard
%    \divide\scratchcounter \maxcard
%    \edef#2{\the\scratchcounter}}

% \PointsToBigPoints{10.53940pt}\test \test
% \PointsToBigPoints{10.53941pt}\test \test
% \PointsToBigPoints{10.53942pt}\test \test

% \PointsToWholeBigPoints{10.53940pt}\test \test
% \PointsToWholeBigPoints{10.53941pt}\test \test
% \PointsToWholeBigPoints{10.53942pt}\test \test

\beginTEX

  \def\PointsToBigPoints#1#2%
    {\scratchdimen#1%
     \scratchdimen.996264\scratchdimen
     \edef#2{\withoutpt\the\scratchdimen}}

  \def\PointsToWholeBigPoints#1#2%
    {\scratchdimen#1%
     \scratchdimen.996264\scratchdimen
     \scratchcounter\scratchdimen
     \advance\scratchcounter \medcard
     \divide\scratchcounter \maxcard
     \edef#2{\the\scratchcounter}}

\endTEX

\beginETEX \dimexpr \numexpr

%   \def\PointsToBigPoints#1#2%
%     {\edef#2{\withoutpt\the\dimexpr(.996264\dimexpr(#1))}}

%   \def\PointsToWholeBigPoints#1#2%
%     {\edef#2{\the\numexpr(\numexpr(\dimexpr(.996264\dimexpr(#1)))/\maxcard)}}

  \def\PointsToBigPoints#1#2%
    {\edef#2{\withoutpt\the\dimexpr.996264\dimexpr#1\relax\relax}}

  \def\PointsToWholeBigPoints#1#2%
    {\edef#2{\the\numexpr\dimexpr.996264\dimexpr#1\relax\relax/\maxcard\relax}}

\endETEX

\def\ScaledPointsToBigPoints     #1{\PointsToBigPoints     {\number#1\scaledpoint}}
\def\ScaledPointsToWholeBigPoints#1{\PointsToWholeBigPoints{\number#1\scaledpoint}}

%D \macros
%D   {PointsToReal}
%D
%D Points can be stripped from their suffix by using
%D \type{\withoutpt}. The next macro enveloppes this macro.
%D
%D \starttyping
%D \PointsToReal {dimension} \target
%D \stoptyping

\def\PointsToReal#1#2%
  {\scratchdimen#1%
   \edef#2{\withoutpt\the\scratchdimen}}

%D \macros
%D  {dontleavehmode}
%D
%D Sometimes when we enter a paragraph with some command, the
%D first token gets the whole first line. We can prevent this
%D by saying:
%D
%D \starttyping
%D \dontleavehmode
%D \stoptyping
%D
%D This command is used in for instance the language module
%D \type{lang-ini}. The first version was:
%D
%D \starttyping
%D \def\dontleavehmode{\ifhmode\else\ifmmode\else$ $\fi\fi}
%D \stoptyping
%D
%D Next, Taco came with a better alternative (using mathsurround):
%D
%D \starttyping
%D \def\dontleavehmode
%D   {\ifhmode\else \ifmmode\else
%D      {\mathsurround\zeropoint\everymath\emptytoks$ $}%
%D    \fi \fi}
%D \stoptyping
%D
%D And finaly we got the following alternative, one that avoids
%D interfering grouping at the cost of a box.

\newbox\@@dlhbox

\unexpanded \def\dontleavehmode
  {\ifhmode\else \ifmmode\else
     \setbox\@@dlhbox\hbox{\mathsurround\zeropoint\everymath\emptytoks$ $}\unhbox\@@dlhbox
   \fi \fi}

% Also ok, but more sensitive to lookahead expansion is:
%
% \def\dontleavehmode{\ifvmode \indent \fi}
%
% which assumes indent is kept unchanged. Protecting the macro is only
% possible in etex (watch out: \unexpanded in context is eq to \protected).
%
% \unexpanded \def\dontleavehmode{\ifvmode \indent \fi} % functional spec TH

%D But, if you run a recent version of \TEX, we can use the new
%D primitive:

\ifx\normalquitvmode\undefined \else \let\dontleavehmode\normalquitvmode \fi

%D \macros
%D   {uppercasestring,lowercasestring}
%D
%D The names tell what they do:
%D
%D \starttyping
%D \uppercasestring somestring\to\somestring
%D \lowercasestring somestring\to\somestring
%D \stoptyping
%D
%D the first argument may be a \type{\macro}.

\def\uppercasestring#1\to#2% first @EA redundant
  {\edef#2{#1}\@EA\uppercase\@EA{\@EA\dodoglobal\@EA\edef\@EA#2\@EA{#2}}}

\def\lowercasestring#1\to#2% first @EA redundant
  {\edef#2{#1}\@EA\lowercase\@EA{\@EA\dodoglobal\@EA\edef\@EA#2\@EA{#2}}}

%D \macros
%D   {handletokens}
%D
%D With the next macro we enter a critical area of macro
%D expansion. What we want is a macro that looks like:
%D
%D \starttyping
%D \handletokens some tokens\with \somemacro
%D \stoptyping
%D
%D At first sight the next implementation will suffice, but
%D running this one shows that we loose the spaces. This is no
%D surprise because we grab arguments and spaces preceding those
%D are just ignored.
%D
%D \starttyping
%D \def\nohandletokens#1\end%
%D   {}
%D
%D \def\dohandletokens#1#2\end%
%D   {\ifx#1\endoftoken
%D      \expandafter\nohandletokens
%D    \else
%D      \docommand{#1}%
%D      \expandafter\dohandletokens
%D    \fi
%D    #2\end}
%D
%D \long\def\handletokens#1\with#2%
%D   {\let\docommand=#2\relax
%D    \dohandletokens#1\endoftoken\end}
%D \stoptyping
%D
%D A second approach therefore grabs the individual characters
%D by using \type{\afterassignment}, in which case the space is
%D read in as space.
%D
%D \starttyping
%D \def\dodohandletokens%
%D   {\ifx\next\end \else
%D      \docommand{\next}%
%D      \expandafter\dohandletokens
%D    \fi}
%D
%D \def\dohandletokens
%D   {\afterassignment\dodohandletokens\let\next= }
%D
%D \long\def\handletokens#1\with#2%
%D   {\let\docommand=#2%
%D    \dohandletokens#1\end}
%D \stoptyping

%D A bonus example:
%D
%D \starttyping
%D \hbox{\handletokens tekst en meer tekst\with\ruledhbox}
%D
%D \def\weetikveel#1{\if#1\blankspace\space\else\ruledhbox{#1}\fi}
%D
%D \hbox{\handletokens tekst en meer tekst\with\weetikveel}
%D \stoptyping

%D \macros
%D   {counttoken,counttokens}
%D
%D For the few occasions that we want to know the number of
%D specific tokens in a string, we can use:
%D
%D \starttyping
%D \counttoken  token\in string\to \count
%D \counttokens          string\to \count
%D \stoptyping
%D
%D This macro, that for instance is used in \type{cont-tab},
%D takes a real counter. The macro can be preceded by \type
%D {\doglobal}.

\def\counttoken#1\in#2\to#3%
  {\redoglobal#3\zerocount
   \def\!!stringa{#1}%
   \def\!!stringb{\end}%
   \def\docounttoken##1% obeys {}
     {\def\!!stringc{##1}%
      \ifx\!!stringb\!!stringc \else
        \ifx\!!stringa\!!stringc
          \dodoglobal\advance#3 \plusone
        \fi
        \expandafter\docounttoken
      \fi}%
   \docounttoken#2\end
   \resetglobal}

% \def\counttoken#1\in#2\to#3%
%   {\redoglobal#3\zerocount
%    \def\!!stringa{#1}%
%    \def\docounttoken##1% obeys {}
%      {\def\!!stringb{##1}%
%       \ifx\!!stringa\!!stringb
%         \dodoglobal\advance#3\plusone
%       \fi}%
%    \handletokens#1\with\docounttoken
%    \resetglobal}

\def\counttokens#1\to#2%
  {\redoglobal#2\zerocount
   \def\docounttoken##1{\dodoglobal\advance#2\plusone}%
   \handletokens#1\with\docounttoken
   \resetglobal}

%D \macros
%D   {splitofftokens}
%D
%D Running this one not always gives the expected results.
%D Consider for instance the macro for which I originally
%D wrote this token handler.

\long\def\splitofftokens#1\from#2\to#3%
  {\ifnum#1>\zerocount
     \scratchcounter#1\relax
     \def\dosplitofftokens##1%
       {\ifnum\scratchcounter>\zerocount
          \advance\scratchcounter \minusone
          \edef#3{#3##1}%
        \fi}%
   % \let#3\empty % #3 can be #2, so:
     \@EA\let\@EA#3\@EA\empty
     \@EA\handletokens#2\with\dosplitofftokens
   \else
     \edef#3{#2}%
   \fi}

%D This macro can be called like:
%D
%D \startbuffer[example]
%D \splitofftokens10\from01234567 890123456789\to\test [\test]
%D \stopbuffer
%D
%D However, the characters that we expect to find in
%D \type{\test} just don;t show up there. The reason for this
%D is not that logical but follows from \TEX's sometimes
%D mysterious way of expanding. Look at this:
%D
%D \startbuffer[next]
%D \def\next{a} \edef\test{\next}                  [\test]
%D \let\next=b  \edef\test{\test\next}             [\test]
%D \let\next=c  \edef\test{\next}                  [\test]
%D \let\next=d  \edef\test{\test\next}             [\test]
%D \let\next=e  \@EA\edef\@EA\test\@EA{\test\next} [\test]
%D \stopbuffer
%D
%D \typebuffer[next]
%D
%D Careful reading shows that inside an \type{\edef} macro's
%D that are \type{\let} are not expanded!
%D
%D \unprotect\getbuffer[next]\protect
%D
%D That's why we finally end up with a macro that looks
%D ahead by using an assignment, this time by using \type
%D {\futurelet}, and grabbing an argument as well. That
%D way we can handle the sentinal, a blank space and grouped
%D tokens.

\def\dohandletokens % \nexthandledtoken is part of interface
  {\futurelet\nexthandledtoken\dodohandletokens}

\long\def\handletokens#1\with#2%
  {\gdef\dododohandletokens{#2}% permits more complex #2's
   \dohandletokens#1\end}

%D A previous version said \type{\docommand=#2}, but to enable
%D use in alignments, I decided to use another placeholder, one
%D that is not sensitive to the global assignment.

%D This alternatives does not handle grouped tokens well, so
%D next we had (for a short moment):
%D
%D \starttyping
%D \def\dodohandletokens#1%
%D  {\ifx\nexthandledtoken\blankspace
%D     \dododohandletokens{ }%
%D   \fi
%D   \ifx#1\end \else
%D     \dododohandletokens{#1}%
%D     \expandafter\dohandletokens
%D   \fi}
%D \stoptyping
%D
%D This one failed on a trailing space, something we
%D encounter in \JAVASCRIPT\ cleaning.
%D
%D \starttyping
%D \def\dodohandletokens#1%
%D   {\ifx\nexthandledtoken\blankspace
%D      \dododohandletokens{ }%
%D    \fi
%D    \ifx\nexthandledtoken\end \else
%D      \dododohandletokens{#1}%
%D      \expandafter\dohandletokens
%D    \fi}
%D \stoptyping
%D
%D So, now we have:

\def\dodohandletokens % can be sped up
  {\ifx\nexthandledtoken\blankspace
     \def\next * {\dododohandletokens{ }\dohandletokens}%
   \else\ifx\nexthandledtoken\end
     \let\next\gobbletwoarguments
   \else
     \long\def\next *##1{\dododohandletokens{##1}\dohandletokens}%
   \fi\fi
   \next *}

%D This macro is tested on:
%D
%D \def\xxx#1{[#1]}
%D
%D \startlines
%D \handletokens         abc\with\xxx
%D \handletokens       a b c\with\xxx
%D \handletokens     a  b  c\with\xxx
%D \handletokens      a{bc}d\with\xxx
%D \handletokens a\space bc \with\xxx
%D \stoplines
%D
%D And our previous example shows up as:
%D
%D \getbuffer[example]

%D \macros
%D   {iftrialtypesetting, ifvisible}
%D
%D The next boolean is at first sight a strange one. Sometimes
%D one does a trial typesetting run, for instance to determine
%D dimensions. Some mechanisms, like object inclusion, can fail
%D on such trials. Temporary setting the next boolean to true,
%D helps a lot. The second boolena can be used to inhibit
%D processing completely.

\newif\iftrialtypesetting  \trialtypesettingfalse
\newif\ifvisible           \visibletrue

%D \macros
%D   {startlocal, startglobal}
%D
%D The next four macros are rather self explaining:
%D
%D \starttyping
%D \startlocal
%D   whatever assignments
%D \stoplocal
%D
%D \startglobal
%D   whatever assignments
%D \stopglobal
%D \stoptyping
%D
%D These macros are meant for those who know the difference
%D between local and global assignments and are aware of the
%D possible unwanted side effect

\def\dostartglobaldefs#1#2%
  {\edef\!!stringa{\the\globaldefs}%
   \ifnum\globaldefs#10
     \globaldefs-\globaldefs
   \fi
   \advance\globaldefs#21
   \letvalue{@gd@\the\globaldefs}\!!stringa}

\def\dostopglobaldefs%
  {\doifdefinedelse{@gd@\the\globaldefs}
     {\globaldefs\getvalue{@gd@\the\globaldefs}\relax}
     {\globaldefs\zerocount}}

\def\startlocal  {\dostartglobaldefs>-}
\def\stoplocal   {\dostopglobaldefs}
\def\startglobal {\dostartglobaldefs<+}
\def\stopglobal  {\dostopglobaldefs}

%D \macros
%D   {twodigitrounding}
%D
%D When using \type {\special}s or \type {\pdfliteral}s, it
%D sometimes makes sense to limit the precission. The next
%D macro rounds a real number to two digits. It takes one
%D argument and only works in \ETEX.

\beginTEX

  \let\integerrounding   \firstofoneargument
  \let\onedigitrounding  \firstofoneargument
  \let\twodigitrounding  \firstofoneargument
  \let\threedigitrounding\firstofoneargument

\endTEX

\beginETEX \dimexpr

  \def\dointegerrounding   #1.#2\relax      {#1}
  \def\doonedigitrounding  #1.#2#3\relax    {\ifx#2*#1\else#1.#2\fi}
  \def\dotwodigitrounding  #1.#2#3#4\relax  {\ifx#2*#1\else#1.#2#3\fi}
  \def\dothreedigitrounding#1.#2#3#4#5\relax{\ifx#2*#1\else#1.#2#3#4\fi}

  \def\integerrounding#1%
    {\@EA\@EA\@EA\dointegerrounding   \@EA\WITHOUTPT\the\dimexpr#1\points+.5\points   \relax      .\relax}
  \def\onedigitrounding#1%
    {\@EA\@EA\@EA\doonedigitrounding  \@EA\WITHOUTPT\the\dimexpr#1\points+.05\points  \relax  00.*0\relax}
  \def\twodigitrounding#1%
    {\@EA\@EA\@EA\dotwodigitrounding  \@EA\WITHOUTPT\the\dimexpr#1\points+.005\points \relax 000.*00\relax}
  \def\threedigitrounding#1%
    {\@EA\@EA\@EA\dothreedigitrounding\@EA\WITHOUTPT\the\dimexpr#1\points+.0005\points\relax0000.*00\relax}

%   \def\dointegerrounding   #1.#2\relax      {#1}
%   \def\doonedigitrounding  #1.#2#3\relax    {#1.#2}
%   \def\dotwodigitrounding  #1.#2#3#4\relax  {#1.#2#3}
%   \def\dothreedigitrounding#1.#2#3#4#5\relax{#1.#2#3#4}

%   \def\integerrounding   #1{\@EA\@EA\@EA\dointegerrounding   \@EA\WITHOUTPT\the\dimexpr   #1\points+.5\points\relax   \relax}
%   \def\onedigitrounding  #1{\@EA\@EA\@EA\doonedigitrounding  \@EA\WITHOUTPT\the\dimexpr  #1\points+.05\points\relax  0\relax}
%   \def\twodigitrounding  #1{\@EA\@EA\@EA\dotwodigitrounding  \@EA\WITHOUTPT\the\dimexpr #1\points+.005\points\relax 00\relax}
%   \def\threedigitrounding#1{\@EA\@EA\@EA\dothreedigitrounding\@EA\WITHOUTPT\the\dimexpr#1\points+.0005\points\relax000\relax}

%   \def\integerroundeddimen   #1{\@EA\@EA\@EA\dointegerrounding   \@EA\WITHOUTPT\the\dimexpr   #1+.5\points\relax   \relax}
%   \def\onedigitroundeddimen  #1{\@EA\@EA\@EA\doonedigitrounding  \@EA\WITHOUTPT\the\dimexpr  #1+.05\points\relax  0\relax}
%   \def\twodigitroundeddimen  #1{\@EA\@EA\@EA\dotwodigitrounding  \@EA\WITHOUTPT\the\dimexpr #1+.005\points\relax 00\relax}
%   \def\threedigitroundeddimen#1{\@EA\@EA\@EA\dothreedigitrounding\@EA\WITHOUTPT\the\dimexpr#1+.0005\points\relax000\relax}

\endETEX

%D \macros
%D   {processcontent}
%D
%D This is the first occasion where \TEX\ and \ETEX\ are no
%D longer compatible, although in many cases things go ok.
%D Beware of verbatim, i.e. catcode changes.
%D
%D \starttyping
%D \def\starthans%
%D   {\processcontent{stophans}\test{\message{\test}\wait}}
%D \stoptyping
%D
%D This macro is first used in the tabulation macros.

\def\processcontent#1%
  {\begingroup\@EA\doprocesscontent\csname#1\endcsname}

%\beginTEX

\def\doprocesscontent#1#2#3%
  {\long\def\doprocesscontent##1#1%
     {\endgroup\long\def#2{##1}#3}%
   \doprocesscontent}

%\endTEX

% Hm. Side effect, spaces after \type{\test} in verbatim.
% must set eof token

%\beginETEX \scantokens
%
%\def\doprocesscontent#1#2#3%
%  {\long\def\doprocesscontent##1#1%
%     {\egroup\long\def#2{\scantokens{##1}}#3}%
%   \doprocesscontent}
%
%\endETEX

%D \macros
%D   {dogobblesingleempty, dogobbledoubleempty}
%D
%D These two macros savely grab and dispose two arguments.

\def\dogobblesingleempty{\dosingleempty\dodogobblesingleempty}
\def\dogobbledoubleempty{\dodoubleempty\dodogobbledoubleempty}

\def\dodogobblesingleempty    [#1]{}
\def\dodogobbledoubleempty[#1][#2]{}

\let\gobblesingleempty\dogobblesingleempty % also used
\let\gobbledoubleempty\dogobbledoubleempty % also used

%D \macros
%D   {sortcommalist,sortcommacommand,
%D    donumericcompare,comparedresult}
%D
%D Sometimes we need to sort a commalist, so here is Taco's
%D solution. This will in many cases be a list that is stored
%D in a \type{\csname}, so both commalist and commacommands are
%D supported. The sorting algorithm is very simple, so the list
%D should not be too long or sorting will be very slow.
%D
%D \starttyping
%D \sortcommalist[10,2,4,5,6,1,2,3,4,10,20]\donumericcompare
%D
%D \def\test{10,2,4,5,6,1,2,3,4,10,20}
%D
%D \sortcommacommand[\test]\donumericcompare
%D \stoptyping
%D
%D In both cases, the result is available in the macro \type
%D {\sortedcommalist}.
%D
%D Parameter \type{#2} is a macro that should accept two
%D parameters, and it has to decide which one is larger, by
%D setting the counter \type{\comparedresult} to~0 (for equal),
%D 1~(if it's first argument is larger), or~2 (if it's second
%D argument is larger).
%D
%D As said, these macro are largely written by Taco, and are
%D (maybe therefore) also the first application of \type
%D {\replaceincommalist}.

\newcount\comparedresult

\def\sortcommacommand[#1]%
  {\@EA\sortcommalist\@EA[#1]}

\def\sortcommalist[#1]#2%
  {\getcommalistsize[#1]%
   \ifnum\commalistsize>1
     \let\sortedcommalist\empty
     \let\comparecommand#2%
     \processcommalist[#1]\dosortcommacommand
   \else
     \def\sortedcommalist{#1}%
   \fi}

\def\dosortcommacommand#1%
  {\ifx\sortedcommalist\empty
     \def\sortedcommalist{#1}%
   \else
     \def\!!tempa{#1}%
     \ifx\!!tempa\empty\else
       \scratchcounter\plusone
       \@EA\getcommalistsize\@EA[\sortedcommalist]%
       \@EA\processcommalist\@EA[\sortedcommalist]\docompareitems
     \fi
   \fi}

%D All those \type{\expandafter}'s are there because I do not
%D want to use \type{\edef}.

\def\docompareitems#1%
  {\doifnotempty{#1}
     {\@EA\comparecommand\@EA{\!!tempa}{#1}\relax
     %\ifcase\compareresult % equal
      \ifnum\comparedresult<2
        \ifnum\scratchcounter=\commalistsize
          \@EA\@EA\@EA\def\@EA\@EA\@EA\sortedcommalist
          \@EA\@EA\@EA{\@EA\sortedcommalist\@EA,\!!tempa}%
        \fi
     %\or % new element larger
     %  \ifnum\scratchcounter=\commalistsize
     %    \@EA\@EA\@EA\def\@EA\@EA\@EA\sortedcommalist
     %    \@EA\@EA\@EA{\@EA\sortedcommalist\@EA,\!!tempa}%
     %  \fi
      \else % old element larger
        \@EA\def\@EA\newcommalistelement\@EA{\!!tempa,#1}%
        \replaceincommalist\sortedcommalist\scratchcounter
        \expandafter\quitcommalist
      \fi}%
      \advance\scratchcounter \plusone} % bug, was \minusone

%D The macro \type{\donumericcompare} considers everything
%D that is not a number to be larger than any number.

\def\donumericcompare#1#2%
  {\doifnumberelse{#1}
     {\doifnumberelse{#2}
        {\ifnum#1>#2\relax
           \comparedresult\plusone       % #1 is larger
         \else\ifnum#1<#2\relax
           \comparedresult\plustwo       % #2 is larger
         \else
           \comparedresult\zerocount     % both are equal
         \fi\fi}
        {\comparedresult\plustwo}}
     {\comparedresult\plusone}}

%D \macros
%D   {@True, @False, @Not, @And}
%D
%D Some predicate logic functions, used in for instance the
%D math module.

\def\@True    {00}
\def\@False   {01}
\def\@Not   #1{0\ifcase#11 \or\@EA 1\else \@EA 0\fi}
\def\@And #1#2{0\ifcase#1#2 \@EA 0\else \@EA 1\fi}

%D \macros
%D   {setdimensionwithunit, freezedimensionwithunit}
%D
%D The next assignments are all valid:
%D
%D \starttyping
%D \setdimensionwithunit\scratchdimen{10}  {cm}
%D \setdimensionwithunit\scratchdimen{10cm}{cm}
%D \setdimensionwithunit\scratchdimen{10cm}{}
%D \freezedimensionwithunit\SomeWidth{\textwidth}
%D \freezedimensionwithunit\SomeDepth{\dp\strutbox}
%D \stoptyping
%D
%D As an alternative for the next macro we can use a global
%D assignment inside a box. The \type{\empty}'s permits
%D gobbling while preventing spurious \type{\relax}'s.

\def\setdimensionwithunit#1#2#3% number unit dimension / nice trick
  {\afterassignment\gobblefourarguments#1=#2#3pt\relax\empty\empty\empty\empty}

\def\freezedimensionwithunit#1#2%
  {\setdimensionwithunit\scratchdimen#1{#2}\edef#1{\the\scratchdimen}}

%D \macros
%D   {doifsometokselse}
%D
%D Not that fast I guess, but here's a way to test for token
%D registers being empty.

\def\doifsometokselse#1%     % #2#3%
  {\edef\!!stringa{\the#1}%
   \ifx\!!stringa\empty      % #3\else#2\fi}
     \expandafter\secondoftwoarguments
   \else
     \expandafter\firstoftwoarguments
   \fi}

%D \macros
%D   {startstrictinspectnextcharacter}
%D
%D This one if for Taco's bibliography module:

\let\normalinspectnextcharacter\inspectnextcharacter

\def\strictinspectnextcharacter% no user macro !
  {\ifx\nexttoken\charactertoken
     \expandafter\!!stringa
   \else
     \expandafter\!!stringb
   \fi}

% better: push/pop

\def\startstrictinspectnextcharacter
  {\let\inspectnextcharacter\strictinspectnextcharacter}

\def\stopstrictinspectnextcharacter
  {\let\inspectnextcharacter\normalinspectnextcharacter}

\def\strictdoifnextoptionalelse#1#2%
  {\startstrictinspectnextcharacter
   \doifnextcharelse[{\stopstrictinspectnextcharacter#1}{\stopstrictinspectnextcharacter#2}}

%D \macros
%D   {gobblespacetokens}
%D
%D This macro needs a speed-up!

%\def\gobblespacetokens
%  {\doifnextcharelse\empty\donothing\donothing} % no {}\do\do !

\def\gobblespacetokens
  {\afterassignment\nexttoken\let\nexttoken=}

%D \macros
%D   {verbatimargument}
%D
%D As the name says, this macro converts its argument to a
%D (rather safe) string.

\def\verbatimstring#1%
  {\convertargument#1\to\ascii\ascii}

%D These are needed in ordinal number conversions:

\def\lastdigit#1%
  {\@EA\thelastdigit\number#1\relax}

\def\thelastdigit#1#2%
  {\ifx#2\relax#1\else\@EA\thelastdigit\@EA#2\fi}

\def\lasttwodigits#1%
  {\@EA\thelasttwodigits\@EA0\number#1\relax}

\def\thelasttwodigits#1#2#3% 0 dig ... \relax
  {\ifx#3\relax#1#2\else\@EA\thelasttwodigits\@EA#2\@EA#3\fi}

%D \macros
%D   {serializecommalist}
%D
%D Concatenate commalists:

\def\serializecommalist[#1]%
  {\let\serializedcommalist\empty
   \def\docommand##1{\edef\serializedcommalist{\serializedcommalist##1}}%
   \processcommacommand[#1]\docommand}

%D \macros
%D   {purenumber}
%D
%D Sometimes we need control over when \TEX\ stops reading a
%D number, especially in full expandable macros where using
%D \type {\relax} would lead to disasters.
%D
%D \starttyping
%D \ifodd\purenumber{...}\space ... \else ... \fi
%D \stoptyping
%D
%D Here we use a space as number delimiter in combination
%D with a space- and relax-less \type {\purenumber}. This
%D macro works ok with \type {\the}, \type {\number} as well
%D as \ETEX's \type {\numexpr}.

\def\purenumber#1{\@EA\firstofoneargument\@EA{\number#1}}

%D \macros
%D   {filterfromvalue}
%D
%D \starttyping
%D \setvalue{xx}{{A}{B}{C}}
%D
%D \filterfromvalue{xx}{3}{3}
%D \filterfromvalue{xx}{3}{2}
%D \filterfromvalue{xx}{3}{1}
%D \stoptyping
%D
%D An alternative is to store 'max' in the list, say:
%D
%D \starttyping
%D \setvalue{xx}{3{A}{B}{C}}
%D
%D \filterfromvalues{3}{xx}{3}
%D \filterfromvalues{3}{xx}{2}
%D \filterfromvalues{3}{xx}{1}
%D \stoptyping
%D
%D I'll implement this when I'm in \quotation {writing dirty
%D macros mood}.

\def\dofilterfromstr#1#2% max n
  {\ifcase#1\or
     \ifcase#2\or
       \strippedcsname\firstofoneargument
     \else
       \strippedcsname\gobbleoneargument
     \fi
   \or
     \ifcase#2\or
       \strippedcsname\firstoftwoarguments
     \or
       \strippedcsname\secondoftwoarguments
     \else
       \strippedcsname\gobbletwoarguments
     \fi
   \or
     \ifcase#2\or
       \strippedcsname\firstofthreearguments
     \or
       \strippedcsname\secondofthreearguments
     \or
       \strippedcsname\thirdofthreearguments
     \else
       \strippedcsname\gobblethreearguments
     \fi
   \or
     \ifcase#2\or
       \strippedcsname\firstoffourarguments
     \or
       \strippedcsname\secondoffourarguments
     \or
       \strippedcsname\thirdoffourarguments
     \or
       \strippedcsname\fourthoffourarguments
     \else
       \strippedcsname\gobblefourarguments
     \fi
   \or
     \ifcase#2\or
       \strippedcsname\firstoffivearguments
     \or
       \strippedcsname\secondoffivearguments
     \or
       \strippedcsname\thirdoffivearguments
     \or
       \strippedcsname\fourthoffivearguments
     \or
       \strippedcsname\fifthoffivearguments
     \else
       \strippedcsname\gobblefivearguments
     \fi
   \fi}

\def\filterfromvalue#1#2#3% value max n
  {\@EA\@EAEAEA\csname                   % we use the fact that an
     \@EA\ifx\csname#1\endcsname\relax   % undefined cs has become \relax
       \strippedcsname\gobbleoneargument % which we then gobble here
     \else
       \dofilterfromstr{#2}{#3}%
     \fi
     \endcsname\csname#1\endcsname}

\def\filterfromnext#1#2% max n {..}{..}{..}{..}
  {\csname\dofilterfromstr{#1}{#2}\endcsname}

%D \macros
%D   {definemeasure}
%D
%D \starttyping
%D \definemeasure[mywidth][\dimexpr(\textwidth-1cm)]
%D
%D ... \measure{mywidth} ...
%D \stoptyping

\def\??dm{@@dm} % brrr

\def\definemeasure
  {\dodoubleargument\dodefinemeasure}

\def\dodefinemeasure[#1][#2]%
  {\setvalue{\??dm#1}{#2}}

% #2 could be omitted, but we want to support spaces
%
% \setmeasure {x}  {1cm}
% \setmeasure {xx} {1cm}
% \setmeasure {xxx}{1cm}

\def\setmeasure #1#2{\setvalue{\??dm#1}{#2}} % quick way
\def\setemeasure#1#2{\setevalue{\??dm#1}{#2}} % quick way
\def\setgmeasure#1#2{\setgvalue{\??dm#1}{#2}} % quick way
\def\setxmeasure#1#2{\setxvalue{\??dm#1}{#2}} % quick way

\def\measure#1%
  {\ifcsname\??dm#1\endcsname\csname\??dm#1\endcsname\else\zeropoint\fi}

%D \macros
%D   {doifdimensionelse}
%D
%D This is a dirty one: we simply append a unit and discard it when needed.

\def\doifdimensionelse#1%
  {\afterassignment\dodoifdimensionelse\scratchdimen#1pt\relax}

\def\dodoifdimensionelse#1%
  {\ifx#1\relax
     \expandafter\secondoftwoarguments
   \else % #1=p ... t\relax
     \expandafter\thirdoffourarguments
   \fi}

%D \macros
%D   {comparedimension,comparedimensioneps}
%D
%D This is a dirty one: we simply append a unit and discard it when needed.

\newdimen\roundingeps \roundingeps=10sp

\def\comparedimension#1#2%
  {\chardef\compresult
     \ifdim#1<#2%
       \zerocount
     \else\ifdim#1<#2%
       \plusone
     \else
       \plustwo
     \fi\fi}

\beginETEX

\def\comparedimensioneps#1#2%
  {\chardef\compresult
     \ifdim\dimexpr#1-#2\relax<\roudingeps
       \zerocount
     \else\ifdim\dimexpr#2-#1\relax<\roudingeps
       \zerocount
     \else\ifdim#1<#2%
       \plusone
     \else
       \plustwo
     \fi\fi\fi}

\endETEX

\beginTEX

\newdimen\comparedimen

\def\comparedimensioneps#1#2%
  {\comparedimen#1\advance\comparedimen-#2\relax
   \chardef\compresult
     \ifdim\comparedimen<\roudingeps
       \zerocount
     \else\ifdim-\comparedimen<\roudingeps
       \zerocount
     \else\ifdim#1<#2%
       \plusone
     \else
       \plustwo
     \fi\fi\fi}

\endTEX

\protect \endinput