syst-new.mkii / last modification: 2020-01-30 14:15
%D \module
%D   [       file=syst-new,
%D        version=1997.01.03,
%D          title=\CONTEXT\ Support Macros,
%D       subtitle=New Ones,
%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.

%D Code from this module will move. For instance to
%D syst-dat.tex (datastructures).

\unprotect

% pretty ugly but fast

% \copycsname xxx\endcsname\csname ..\endcsname

\def\copycsname{\@EA\@EA\@EA\let\@EA\@EA\csname}

% \letcscsname    \crap               \csname ..\endcsname
% \letcsnamecs    \csname ..\endcsname\crap
% \letcsnamecsname\csname ..\endcsname\csname ..\endcsname

\def\letcscsname    {\@EA\let\@EA}
\def\letcsnamecs    {\@EA\let}
\def\letcsnamecsname{\@EA\@EA\@EA\let\@EA\@EA}

% another one, add an item to a commalist

\def\addvalue#1#2% cs item
  {\ifundefined{#1}\@EA\let\csname#1\endcsname\empty\fi
   \expanded{\addtocommalist{#2}\@EA\noexpand\csname#1\endcsname}}

% faster, and looks okay

\def\unspaced#1%
  {\dounspaced#1\end}

\def\dounspaced#1%
  {\ifx#1\end
     \@EA\gobbleoneargument
   \else
     \ifx#1\blankspace\else#1\fi
   \fi
   \dounspaced}

\def\unspaceargument#1\to#2%
  {\defconvertedargument#2{#1}%
   \@EA\edef\@EA#2\@EA{\@EA\unspaced\@EA{#2}}}

\def\unspaceafter#1#2%
  {\edef\ascii{\dounspaced#2\end}\@EA#1\@EA{\ascii}}

% etex, much faster
%
% \def\unspaceargument#1\to#2%
%   {\scratchcounter\catcode'32\catcode32=\@@ignore
%    \scantokens{\edef#2{#1}}%
%    \catcode32=\scratchcounter}

\def\unspaceafter#1#2%
  {\edef\ascii{\dounspaced#2\end}\@EA#1\@EA{\ascii}}

% sometimes handy:

\def\doifhasspaceelse#1%
  {\edef\!!stringa{#1}%
   \expanded{\dodoifhasspaceelse#1\space}\empty\relax}

\def\dodoifhasspaceelse#1 #2#3\relax % \space\empty\relax
  {\ifx\!!stringa\space
     \@EA\firstoftwoarguments
   \else\ifx#2\empty
     \@EAEAEA\secondoftwoarguments
   \else
     \@EAEAEA\firstoftwoarguments
   \fi\fi}

% this will replace loadfile once and alike !!! todo

\def\@flg@{@flg@}

\def\setflag#1%
  {\@EA\dodoglobal\@EA\chardef\csname\@flg@#1\endcsname\zerocount}

\def\resetflag#1%
  {\@EA\dodoglobal\@EA\chardef\csname\@flg@#1\endcsname\plusone}

\let\ifflagged\ifcase

\def\flag#1{\csname\@flg@#1\endcsname}

\def\doifelseflagged#1%
  {\@EA\ifx\csname\@flg@#1\endcsname\relax
     \@EA\secondoftwoarguments
   \else\ifcase\csname\@flg@#1\endcsname
     \@EAEAEA\firstoftwoarguments
   \else
     \@EAEAEA\secondoftwoarguments
   \fi\fi}

\def\doifnotflagged#1%
  {\@EA\ifx\csname\@flg@#1\endcsname\relax
     \@EA\firstofoneargument
   \else\ifcase\csname\@flg@#1\endcsname
     \@EAEAEA\gobbleoneargument
   \else
     \@EAEAEA\firstofoneargument
   \fi\fi}

\def\inheritparameter[#1]#2[#3]#4[#5]% tag tokey fromkey % [bypasses k!prefix]
  {\@EAEAEA\def\@EA\csname\@EA#1\@EA#3\@EA\endcsname\@EA
     {\csname#1#5\endcsname}}

% \buildarray[test][aa,bb,cc,dd,ee,ff]
% \setarrayelement{test}{1}{qq}
% \arrayelement{test}{1}
% \arraylength{test}
%
% \def\buildarray[#1][#2]%
%   {\scratchcounter=0
%    \def\docommand##1%
%      {\advance\scratchcounter by 1
%       \setvalue{@@aa#1\the\scratchcounter}{##1}}%
%    \processcommalist[#2]\docommand
%    \setevalue{@@aa#1}{\the\scratchcounter}}%
%
% \def\setarrayelement#1#2{\setvalue{@@aa#1#2}}
% \def\arrayelement   #1#2{\getvalue{@@aa#1#2}}
% \def\arraylength      #1{\getvalue{@@aa#1}}

% \newsignal\junksignal
%
% \def\setjunksignal%
%   {\ifhmode
%      \hskip\junksignal
%      \let\removejunkspaces\doremovejunkspaces
%    \else
%      \let\removejunkspaces\relax
%    \fi}
%
% \def\doremovejunkspaces%
%   {\doloop{\ifdim\lastskip=\junksignal\unskip\else\exitloop\fi}}

% \def\doifnonzeropositiveelse#1#2#3%
%   {\bgroup
%    \setbox\scratchbox=\hbox{\scratchcounter=0#1}%
%    \ifdim\wd\scratchbox=\!!zeropoint\egroup#2\else\egroup#3\fi}
%
% \def\dodoifnonzeropositiveelse#1#2\end#3#4%
%   {\egroup
%    \ifx#1\relax#3\else#4\fi}
%
% \def\doifnonzeropositiveelse#1%
%   {\bgroup
%    \afterassignment\dodoifnonzeropositiveelse\scratchcounter=0#1\relax\empty\end}

\def\dodoifnonzeropositiveelse#1#2\end % #3#4%
  {\ifx#1\relax
     \ifcase\scratchcounter
       \endgroup
       \@EAEAEA\secondoftwoarguments
     \else
       \endgroup
       \@EAEAEA\firstoftwoarguments
     \fi
   \else
      \endgroup
      \@EA\secondoftwoarguments
   \fi}

\def\doifnonzeropositiveelse#1%
  {\begingroup\afterassignment\dodoifnonzeropositiveelse\scratchcounter=0#1\relax\empty\end}

% here ?

\def\dosetrawvalue #1#2#3{\@EA \def\csname#1#2\endcsname{#3}}
\def\dosetrawevalue#1#2#3{\@EA\edef\csname#1#2\endcsname{#3}}
\def\dosetrawgvalue#1#2#3{\@EA\gdef\csname#1#2\endcsname{#3}}
\def\dosetrawxvalue#1#2#3{\@EA\xdef\csname#1#2\endcsname{#3}}

\def\getrawparameters      {\dogetparameters\dosetrawvalue }
\def\getraweparameters     {\dogetparameters\dosetrawevalue}
\def\getrawgparameters     {\dogetparameters\dosetrawgvalue}
\def\getrawxparameters     {\dogetparameters\dosetrawxvalue}

\def\globalgetrawparameters{\dogetparameters\dosetrawgvalue} % obsolete

\def\splitskip#1%
  {\scratchskip\zeropoint \!!plus \onepoint \!!minus \onepoint
   \advance\scratchskip#1\relax % \relax is realy needed here
   \expandafter\SPLITSKIP\the\scratchskip}

{\catcode`\.=\@@other
 \catcode`\p=\@@other
 \catcode`\l=\@@other
 \catcode`\u=\@@other
 \catcode`\s=\@@other
 \catcode`\m=\@@other
 \catcode`\i=\@@other
 \catcode`\n=\@@other
 \catcode`\t=\@@other
 \gdef\SPLITSKIP#1pt plus #2pt minus #3pt%
   {\DOSPLITSKIP#1 #2 #3 }}

% \def\DOSPLITSKIP#1 #2 #3
%   {\dimen0=#1pt\dimen2=#2pt\dimen4=#3pt
%    \advance\dimen2 -\onepoint
%    \advance\dimen4 -\onepoint}

\def\DOSPLITSKIP#1 #2 #3
  {\dimen0=#1\onepoint
   \dimen2=\dimexpr#2\onepoint-\onepoint\relax
   \dimen4=\dimexpr#3\onepoint-\onepoint\relax}

% \def\minimaxskip#1#2%
%   {\splitskip#2\relax
%    \scratchdimen=#2\relax
%    #2=\scratchdimen
%    \advance#2 by #1\relax}
%
% \def\maximizeskip%
%   {\minimaxskip{-\dimen4}}
%
% \def\maximizeskip%
%   {\minimaxskip{\dimen2}}
%
% \def\maximizespacing%
%   {\maximizeskip\blankskipamount
%    \maximizeskip\parskip
%    \maximizeskip\ctxparskip
%    \maximizeskip\baselineskip
%    \maximizeskip\bigskipamount
%    \maximizeskip\medskipamount
%    \maximizeskip\smallskipamount}

\newcount\modcounter

%\def\DoMod #1by#2to#3%
%  {\modcounter#1\divide\modcounter#2\multiply\modcounter#2%
%   #3#1\advance#3 -\modcounter}
%
%\def\DoDiv #1by#2to#3%
%  {#3#1\divide#3 #2\relax}

\def\dosetmodulo#1#2#3%
  {\modcounter#1\divide\modcounter#2\multiply\modcounter#2%
   #3#1\advance#3-\modcounter}

\def\dosetdivision#1#2#3%
  {#3#1\divide#3 #2\relax}

\def\DoMod#1by#2to#3{\dosetmodulo  {#1}{#2}{#3}}
\def\DoDiv#1by#2to#3{\dosetdivision{#1}{#2}{#3}}

\def\dounprotected#1\par
  {#1\protect}

\def\unprotected
  {\unprotect\dounprotected}

%D Standaard kan een spatie (zoals ~) uitrekken. Dit is in
%D overzichten niet altijd de bedoeling, vandaar:

% \def\fixedspace{\hskip\interwordspace\relax}

%\def\ExpandSecondAfter#1#2#3%
%  {\!!toksa={#2}%
%   \edef\!!stringa{#3}%
%   \edef\expanded%
%     {\noexpand#1{\the\!!toksa}{\!!stringa}}%
%   \expanded}
%
%\def\ExpandThirdAfter#1#2#3#4%
%  {\!!toksa={#2}%
%   \!!toksb={#3}%
%   \edef\!!stringa{#4}%
%   \edef\expanded%
%     {\noexpand#1{\the\!!toksa}{\the\!!toksb}{\!!stringa}}%
%   \expanded}

%\def\indirect#1#2#3%
%  {\@EA#1\@EA#2\@EA{\@EA#3\csname\s!do\string#2\endcsname}%
%   \@EA#1\csname\s!do\string#2\endcsname}
%
%\def\doubleemptied#1#2#3%
%  {\indirect#1#2\dodoublempty}
%
%\indirect\def\stelietsin\dodoubleempty[#1][#2]%
%  {...}
%
%\doubleemptied\def\stelietsin[#1][#2]%
%  {...}

% in mult-set
%
%\def\defaultsetup{def}
%
%\def\selectdefaultsetup#1#2%
%  {\writestatus{setup}{choose #1 setupfile}%
%   \bgroup
%   \endlinechar=-1
%   \global\read16 to \usersetup
%   \egroup
%   \ifx\usersetup\empty
%     \let\usersetup=\defaultsetup
%   \fi
%   \readfile{#2\usersetup}{}{}%
%   \writestatus{setup}{loading #1 setupfile #2\usersetup}}

% awaiting the definitive implementation

\ifx\resettimer\undefined
  \let\resettimer \relax
  \newcount\elapsedtime
\fi

\newcount\featuretest

\def\testfeature#1#2%
  {\def\dotestfeature
     {\advance\featuretest \plusone
      \ifnum\featuretest>#1\else#2\expandafter\dotestfeature\fi}%
   \retestfeature}

\def\retestfeature % timer support is new per 10/5/2005
  {\bgroup
   \ifcase\interactionmode\let\wait\relax\fi
   \writestatus\m!systems{starting feature test}\wait
   \resettimer
   \featuretest\zerocount \dotestfeature
   \writestatus\m!systems{feature test done (\elapsedseconds s)}%
   \wait
   \egroup}

\def\elapsedseconds{\expandafter\withoutpt\the\dimexpr\elapsedtime sp\relax}

\def\showtimer#1%
  {\writestatus{runtime}{\elapsedseconds\space s / #1}}

%  \edef\elapsedtime{\expandafter\withoutpt\the\dimexpr\elapsedtime\relax s}%
%  \writestatus\m!systems{feature test done (\elapsedtime)}%

\def\testfeatureonce#1#2%
  {\let\wait\relax\testfeature{#1}{#2}\end}

%D \macros
%D   {adddimenregister,adddimenmacro}
%D
%D Instead of using numerous \type {\advance}'s, one can use
%D the next macros to add|/|subtract a series of dimensions
%D to a register or macro.
%D
%D \starttyping
%D \adddimenregister 10pt 5pt \paperwidth \to \somedimen
%D \adddimenmacro    10pt 5pt \paperwidth \to \bagger
%D \stoptyping

% \newdimen\dimentoaddto

% \def\adddimenregister#1\to#2% will be obsolete once full etex
%   {\begingroup
%    #2=\zeropoint
%    \dimentoaddto\zeropoint
%    \def\docommand%
%      {\advance#2 \dimentoaddto
%       \futurelet\next\dodocommand}%
%    \def\dodocommand%
%      {\ifx\next\relax
%         \expanded{\endgroup#2=\the#2}%
%       \else
%         \@EA\afterassignment\@EA\docommand\@EA\dimentoaddto
%       \fi}%
%    \docommand#1\relax}

% \def\adddimenmacro#1\to#2%
%   {\adddimenregister#1\to\scratchdimen
%    \edef#2{\the\scratchdimen}}

%D \macros
%D   {freezedimenmacro}
%D
%D This macro is use as:
%D
%D \starttyping
%D \freezedimenmacro\leftmargindistance
%D \stoptyping

% \def\freezedimenmacro#1%
%   {\scratchdimen#1\edef#1{\the\scratchdimen}}

\def\freezedimenmacro#1%
  {\edef#1{\the\dimexpr#1}}

%D The next one is slower:
%D
%D \starttyping
%D \def\freezedimenmacro#1{\edef#1{\the\dimexpr(#1)}}
%D \stoptyping

% \newcount\rawrecursecounter
%
% \def\rawrecurselevel{\the\rawrecursecounter}%
%
% \def\dorawrecurse#1#2%
%   {\rawrecursecounter\plusone
%    \let\oldrecurselevel\recurselevel
%    \let\recurselevel\rawrecurselevel
%    \def\dodorawrecurse
%      {\ifnum\rawrecursecounter>#1\relax
%         \let\recurselevel\oldrecurselevel
%       \else
%         #2\advance\rawrecursecounter \plusone
%         \expandafter\dodorawrecurse
%       \fi}%
%    \dodorawrecurse}

%D The next macro negates a macro (dimension or number, or actually, whatever.
%D It's a typical example of \type {\if} usage:
%D
%D \starttyping
%D \if-\whatever \else-\whatever\fi => else => -whatever
%D \if--\whatever\else-\whatever\fi => then =>  whatever
%D \stoptyping

\def\negated#1{\if-#1\else-#1\fi} % does only work in macros or text

% This permits things like ^\index{hans}^, where hans is
% duplicated in the text.

\newif\ifduplicate

\bgroup

\gdef\checkduplication % in line with Knuth
  {\ifmmode\expandafter^\else\expandafter\startduplication\fi}

\gdef\insideduplication
  {\ifmmode\expandafter^\else\expandafter\egroup\fi}

\catcode`\^=\@@active

\gdef\enableduplication
  {\catcode`\^=\@@active \let^\checkduplication}

\gdef\disableduplication
  {\catcode`\^=\@@superscript}

\gdef\startduplication
  {\bgroup \duplicatetrue \let^\insideduplication}

\egroup

\def\gobbleassigndimen#1\\{}

\def\assigndimen#1#2%
  {\afterassignment\gobbleassigndimen#1=#2\!!zeropoint\\}

\def\setusage#1%
  {\@EA\let\csname#1\endcsname\iftrue}

\def\resetusage#1%
  {\@EA\let\csname#1\endcsname\iffalse}

\beginTEX

\def\ifusage#1%
  {\@EA\ifx\csname#1\endcsname\relax
     \resetusage{#1}%
   \fi
   \csname#1\endcsname}

\endTEX

\beginETEX \ifcsname

\def\ifusage#1%
  {\ifcsname#1\endcsname\else
     \resetusage{#1}%
   \fi
   \csname#1\endcsname}

\endETEX

%D Very handy, more efficient than \type{{}}, and more readable
%D than \type {\empty}.

\let\donothing\empty

% The following macros are used in XML handling.

% \long\def\dowithstringed#1#2#3#4% " ' space
%   {\if#4"\@EA#1\else\if#4'\@EAEAEA#2\else\@EAEAEA#3\fi\fi#4}
%
% \def\unstringed
%   {\dowithstringed\unstringdouble\unstringsingle\unstringspaced}
%
% \long\def\unstringdouble"#1"{#1}
% \long\def\unstringsingle'#1'{#1}
% \long\def\unstringspaced #1 {#1}
%
% \def\grabstring
%   {\dowithstringed\grabstringdouble\grabstringsingle\grabstringspaced}
%
% \def\dowithgrabbedstring#1%
%   {\def\@@dowithgrabbedstring{#1}%
%    \afterassignment\@@dowithgrabbedstring\grabstring}
%
% \long\def\grabstringdouble"#1"{\scratchtoks{#1}}
% \long\def\grabstringsingle'#1'{\scratchtoks{#1}}
% \long\def\grabstringspaced #1 {\scratchtoks{#1}}

\long\setvalue{@u@s@"}#1#2"{#2} \long\setvalue{@g@s@"}#1#2"{\scratchtoks{#2}}
\long\setvalue{@u@s@'}#1#2'{#2} \long\setvalue{@g@s@'}#1#2'{\scratchtoks{#2}}
\long\setvalue{@u@s@ }#1#2 {#2} \long\setvalue{@g@s@ }#1#2 {\scratchtoks{#2}}

\long\def\unstringed#1{\csname\ifcsname @u@s@#1\endcsname @u@s@#1\else\s!empty\fi\endcsname#1}
\long\def\grabstring#1{\csname\ifcsname @g@s@#1\endcsname @g@s@#1\else\s!empty\fi\endcsname#1}

\def\dowithgrabbedstring#1%
  {\def\@@dowithgrabbedstring{#1}%
   \afterassignment\@@dowithgrabbedstring\grabstring}

\def\expifequalelse#1#2%
  {\@@ifequal#1\relax\relax\@@and#2\relax\relax\@@then}

\def\@@ifequal#1#2\@@and#3%
  {\ifx#1\relax
     \ifx#3\relax
       \@EAEAEA\@@if@@equal@@true
     \else
       \@EAEAEA\@@if@@equal@@false
     \fi
   \else
     \ifx#3\relax
       \@EAEAEAEAEAEA\@@if@@equal@@false
     \else\ifx#1#3%
       % go on
     \else
       \@EAEAEAEAEAEA\@@if@@equal@@false
     \fi\fi
   \fi
   \@@ifequal#2\@@and}

\long\def\@@if@@equal@@true #1\@@then#2#3{#2}
\long\def\@@if@@equal@@false#1\@@then#2#3{#3}

%D new stuff :

\def\partialexpanded#1%
   {\let\@@notexpanded\noexpand
    \long\xdef\@@expanded{\noexpand#1}%
    \let\@@notexpanded\empty
    \@@expanded}

% for Simon ; watch how we make them fully expandable (i.e.
% no \type {\relax}es) popping up

\def\@do@the@number@#1\relax#2\end{#1}

\def\@the@number@#1{\@EA\@do@the@number@\number#1\relax\end}

\def\doifnum#1#2%
  {\ifnum#1=\@the@number@{#2} % space needed
     \expandafter\firstofoneargument
   \else
     \expandafter\gobbleoneargument
   \fi}

\def\doifnotnum#1#2%
  {\ifnum#1=\@the@number@{#2} % space needed
     \expandafter\gobbleoneargument
   \else
     \expandafter\firstofoneargument
   \fi}

\def\doifelsenum#1#2%
  {\ifnum#1=\@the@number@{#2} % space needed
     \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

% \edef\xxxx{\doifnum{1}{2}{no}} \show \xxxx
% \edef\xxxx{\doifnum{2}{2}{yes}} \show \xxxx
% \scratchcounter0 \edef\xxxx{\doifnum{1}{\scratchcounter}{no}} \show \xxxx
% \scratchcounter1 \edef\xxxx{\doifnum{1}{\scratchcounter}{yes}} \show \xxxx

\def\appended#1#2#3{\@EA#1\@EA#2\@EA{#2#3}}
\def\appendvalue #1{\@EA\appended\@EA \def\csname#1\endcsname}
\def\appendgvalue#1{\@EA\appended\@EA\gdef\csname#1\endcsname}

\def\prepended#1#2#3{\scratchtoks{#3}\@EA\@EA\@EA#1\@EA\@EA\@EA#2\@EA\@EA\@EA{\@EA\the\@EA\scratchtoks#2}}
\def\prependvalue #1{\@EA\prepended\@EA \def\csname#1\endcsname}
\def\prependgvalue#1{\@EA\prepended\@EA\gdef\csname#1\endcsname}

%D \macros
%D   {compresscommacommandnrs,compresscommalistnrs,compressedcommalistnrs,
%D    compresscommacommand,compresscommalist,compressedcommalist,
%D    reversecommacommand,reversecommalist,reversedcommalist}
%D
%D The following two list processing macros are needed by Taco's
%D bibliography module. The numbers compressor converts the
%D list in a list of ranges. The normal compressor remove duplicate
%D and empty entries.

\def\compresscommalistnrs[#1]%
  {\let\compressedlist\empty
   \!!counta\maxdimen
   \!!countb\maxdimen
   \processcommalist[#1]\docompresslistnrs
   \ifnum\!!counta=\maxdimen\else\dodocompresslistnrs\fi}

\def\compresscommacommandnrs[#1]%
  {\expanded{\compresscommalistnrs[#1]}}

\def\docompresslistnrs#1%
  {\edef\commalistelement{#1}%
   \ifx\commalistelement\empty\else
     \ifnum\!!counta=\maxdimen
       \!!counta\commalistelement\relax
       \!!countb\!!counta
     \else
       \advance\!!countb\plusone
       \ifnum\commalistelement>\!!countb
         \advance\!!countb\minusone
         \dodocompresslistnrs
         \!!counta\commalistelement\relax
         \!!countb\!!counta
       \fi
     \fi
   \fi}

\def\dodocompresslistnrs
  {\edef\compressedlist
     {\ifx\compressedlist\empty\else\compressedlist,\fi
      {\the\!!counta}{\ifnum\!!countb>\!!counta\the\!!countb\fi}}}

%D \def\test#1{{\tttf#1->\compresscommalistnrs[#1]\defconvertedcommand\ascii\compressedlist\ascii}}
%D \startlines
%D \test{}
%D \test{1}
%D \test{1,3}
%D \test{1,3,4}
%D \test{1,3,3,4,5}
%D \test{1,3,3,4,5,8}
%D \test{1,3,3,4,5,5,8,10}
%D \test{1,3,4,5,8,10,11}
%D \test{1,,3,,4,,5,,8,,10,,11,}
%D \stoplines

\def\compresscommalist[#1]%
  {\let\compressedlist\empty
   \let\!!stringa\empty
   \processcommalist[#1]\docompresslist}

\def\compresscommacommand[#1]%
  {\expanded{\compresscommalist[#1]}}

\def\docompresslist#1%
  {\edef\commalistelement{#1}%
   \ifx\commalistelement\empty \else
     \ifx\!!stringa\commalistelement \else
       \ifx\compressedlist\empty
         \def\compressedlist{#1}%
       \else
         \appended\def\compressedlist{,#1}%
       \fi
       \let\!!stringa\commalistelement
     \fi
   \fi}

%D \def\test#1{{\tttf#1->\compresscommalist[#1]\defconvertedcommand\ascii\compressedlist\ascii}}
%D \startlines
%D \test{}
%D \test{1}
%D \test{1,3}
%D \test{1,3,4}
%D \test{1,3,3,4,5}
%D \test{1,3,3,4,5,8}
%D \test{1,3,3,4,5,5,8,10}
%D \test{1,3,4,5,8,10,11}
%D \test{1,,3,,4,,5,,8,,10,,11,}
%D \stoplines

\def\reversecommalist[#1]%
  {\let\reversedlist\empty
   \processcommalist[#1]\doreverselist}

\def\doreverselist#1%
  {\ifx\reversedlist\empty
     \def\reversedlist{#1}%
   \else
     \prepended\def\reversedlist{#1,}%
   \fi}

\def\reversecommacommand[#1]%
  {\expanded{\reversecommalist[#1]}}

%D \def\test#1{{\tttf#1->\reversecommalist[#1]\defconvertedcommand\ascii\reversedlist\ascii}}
%D \startlines
%D \test{}
%D \test{1}
%D \test{1,3}
%D \test{1,3,4}
%D \test{1,3,3,4,5}
%D \test{1,3,3,4,5,8}
%D \test{1,3,3,4,5,5,8,10}
%D \test{1,3,4,5,8,10,11}
%D \test{1,,3,,4,,5,,8,,10,,11,}
%D \stoplines

%D \macros
%D   {stripstring}
%D
%D Needed in bookmarks:
%D
%D \starttyping
%D {\sanitizePDFdocencoding test \CONTEXT\  test \to\oeps\stripstring\oeps\tttf[\oeps]}
%D \stoptyping

\def\stripstring#1% #1 is \cs
  {\bgroup
   \defconvertedcommand\ascii{#1}%
   \global\let\globalascii\empty
   \donefalse
   \expandafter\handletokens\ascii\with\dostripstring
   \egroup
   \let#1\globalascii}

\def\dostripstring#1%
  {\ifx#1\blankspace
     \donetrue
   \else
     \ifdone\ifx\globalascii\empty\else
       \xdef\globalascii{\globalascii\space}%
       \donefalse
     \fi\fi
     \xdef\globalascii{\globalascii#1}%
   \fi}

%D \macros
%D   {dowithrange}
%D
%D This one is for Mojca Miklavec, who made me aware of the fact that
%D \type {page-imp.tex} was not the best place to hide it.

\def\dowithrange#1#2% #2 takes number
  {\splitstring#1\at:\to\fromrange\and\torange
   \ifx\torange\empty\let\torange\fromrange\fi
   \dostepwiserecurse\fromrange\torange1{#2{\recurselevel}}}

%D \macros {uncompresslist}
%D
%D When given a list like \type{1,4-7,9} as argument, this macro
%D will store the expanded commalist in \type{\uncompressedlist}.
%D
%D \startbuffer
%D \def\MojcaHasToDoTheTasks[#1]#2%
%D   {{\uncompresslist[#1]%
%D     \def\processitem##1{I have to do ##1 #2\par}%
%D     \processcommacommand[\uncompressedlist]\processitem}}
%D
%D \MojcaHasToDoTheTasks [1-4,7,9-11] {until tomorrow}
%D \stopbuffer
%D
%D Here is an example of how to use \type {\uncompresslist}:
%D \typebuffer
%D
%D The output of this is:
%D
%D \getbuffer

\beginETEX \numexpr

\def\uncompresslist[#1]% by TH
  {\let\uncompressedlist\empty
   \def\docompressedlistitem##1-##2-%
     {\@EA\dorecurse\@EA
        {\the\numexpr1+##2-##1\relax}%
        {\@EA\appendtocommalist\@EA{\the\numexpr##1-1+####1\relax}\uncompressedlist}}%
   \def\douncompresslist##1%
     {\doifinstringelse{-}{##1}
        {\docompressedlistitem##1-}
        {\appendtocommalist{##1}\uncompressedlist}}%
   \processcommalist[#1]\douncompresslist}

\endETEX

\beginTEX

\def\uncompresslist[#1]%
  {\def\uncompressedlist{#1}}

\endTEX

%D \macros
%D   {ignoreimplicitspaces}
%D
%D \startbuffer
%D \def\whatever[#1]{\expanded{\definedfont[#1 at 12pt]}\ignorespaces}
%D {a\whatever[Serif]b a\whatever[Serif] b a\whatever[Serif]\space b}
%D \def\whatever[#1]{\expanded{\definedfont[#1 at 12pt]}\ignoreimplicitspaces}
%D {a\whatever[Serif]b a\whatever[Serif] b a\whatever[Serif]\space b}
%D \stopbuffer
%D
%D \typebuffer \getbuffer

\def\ignoreimplicitspaces
  {\doifnextcharelse\relax\relax\relax}

% new
%
% \startnointerference
% all kind of code
% \stopnointerference

\newbox\nointerferencebox

\def\startnointerference
  {\setbox\nointerferencebox\vbox
   \bgroup}

\def\stopnointerference
  {\egroup
   \setbox\nointerferencebox\emptybox}

\protect \endinput


% \def\appendtovaluelist#1#2%
%   {\ifcsname#1\endcsname
%      \expandafter\ifx\csname#1\endcsname\empty
%        \expandafter\def\csname#1\endcsname{#2}%
%      \else
%        \expandafter\def\csname#1\expandafter\expandafter\expandafter\endcsname
%           \expandafter\expandafter\expandafter{\csname#1\endcsname,#2}%
%      \fi
%    \else
%      \expandafter\def\csname#1\endcsname{#2}%
%    \fi}
%
% or
%
% \def\appendtovaluelist#1%
%   {\ifcsname#1\endcsname
%      \expandafter\ifx\csname#1\endcsname\empty
%        \expandafter\noappendtovaluelist\csname#1\expandafter\expandafter\expandafter\endcsname
%      \else
%        \expandafter\doappendtovaluelist\csname#1\expandafter\expandafter\expandafter\endcsname
%      \fi
%    \else
%      \expandafter\noappendtovaluelist\csname#1\expandafter\endcsname
%    \fi}

% \def\doappendtovaluelist#1#2{\expandafter\def\expandafter#1\expandafter{#1,#2}}
% \def\noappendtovaluelist#1#2{\def#1{#2}}

% \appendtovaluelist{mylist}{aap}
% \appendtovaluelist{mylist}{noot}
% \appendtovaluelist{mylist}{mies}

% \showvalue{mylist}