% Copyright 2012-2024, Alexander Shibakov
% This file is part of SPLinT
%
% SPLinT is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% SPLinT is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with SPLinT.  If not, see <http://www.gnu.org/licenses/>.

% basic data manipulation and testing routines; these are not
% specific to any parsing/lexing task and may be used independently;
% register definitions from the `\TeX\ runtime' (trt1.sty) are needed
% by the list and switch macros

\catcode`\@=11

% a nestable loop, needed by the macros in xarithm.sty, included
% immediately after the definition

\def\bloop#1\repeat{#1\bl@op{#1}\repeat\fi}
\def\bl@op#1\repeat\fi{\fi#1\bl@op{#1}\repeat\fi}

\input xarithm.sty

% (unoptimized) stacks will be defined as `list' macros, consisting of \sts{...}\sts{...}... type lists
% in \yypopstack, the second parameter must be a positive number
%
% note: perhaps, replacing \sts with the name of the stack would allow for more economical
% use of the user namespace, however, this will somewhat complicate the macros below, as well
% as make it impossible to assign a different control sequence to the
% stack (which may be considered a feature by itself)

% note: a somewhat clumsy way in which the code below is written is due to the goal of making it
% independent of general use registers (\tempc?); the result is extremely slow code

\def\yyinitstack#1{% to provide consistency with the accelerated macros
    \let#1\empty
}

\long\def\scoopupstack#1#2\stackend#3{\def#3{\sts{#1}#2}}

\def\stackend#1{\def#1{}} % if we got here, the stack is empty

% the following macro is a mild example of expansion tricks

\def\yypopstack#1\by#2{%
    \ifnum#2>\z@
        \yyp@pst@ck{#1}{#2}%
    \fi
}

\def\yyp@pstack#1{%
    \expandafter\space#1%
}

% the definition below is here purely for clarity

\catcode`\.=\active
\let.\expandafter

\def\yyp@pst@ck#1#2{%
    \let\sts\or
    \iffalse{\fi...\def...#1...{...\sts.\ifcase\number\number.\xincrement.{\number#2} \yyp@pstack#1}\else}\fi
}

\catcode`\.=12 % other character

% #1 is the name of the stack, #2 is a token register

\def\yypop#1\into#2{\def\sts{\consumeone{#2}}#1\stackend#1}

\long\def\consumeone#1#2{%
    #1{#2}\let\sts\scoopupstack
}

% pushing stuff on a stack: \yypush{t o k e n s}\on\yyvs or \expandafter\yypush\number\yystate\on\yyss

\long\def\yypush#1\on#2{\expandafter\def\expandafter#2\expandafter{\romannumeral\yyp@sh{#2}{#1}}}

\long\def\yyp@sh#1#2{\expandafter\yyp@@h\expandafter{#1}{#2}}

\long\def\yyp@@h#1#2{0 \sts{#2}#1}

% push register contents on a stack: #1 is a register, #2 is a stack (a control
% sequence that expands to a `\sts{v a l u e}\sts...' list)

\def\yypushr#1\on#2{\expandafter\yypush\expandafter{\the#1}\on#2}

% the first parameter is the stack, the second is the location from the top (a nonnegative number), the third is
% the control sequence that will hold the value;

\def\yyreadstack#1\at#2\to#3{\edef\sts{\noexpand\skipandcount{\number#2}{\noexpand#3}}#1\stackfinish#1}

\def\skipandcount#1#2#3{%
    \ifnum#1=\z@ %we have got to the element we need
        \def#2{#3}%
        \yybreak\ignorestack
    \else
        \yybreak{\edef\sts{\noexpand\skipandcount{\xdecrement{#1}}{\noexpand#2}}}%
    \yycontinue
}

% same as above except read the value into a register

\def\yyreadstackr#1\at#2\to#3{\edef\sts{\noexpand\skipandcountr{\number#2}{#3}}#1\stackfinish#1}

\def\skipandcountr#1#2#3{%
    \ifnum#1=\z@ %we have got to the element we need
        #2#3%
        \yybreak\ignorestack
    \else
        \yybreak{\edef\sts{\noexpand\skipandcountr{\xdecrement{#1}}{\noexpand#2}}}%
    \yycontinue
}

\long\def\ignorestack#1\stackfinish#2{}

\def\stackfinish#1{\def#1{0\message{:stack empty:}}}

% (unoptimized) arrays of integers are represented by a string of tokens `element0 \or element1 \or ...'
% #2 is a register (otherwise the case and the integer from the array `coalesce');
% the following macro was designed to make something like
% \tempca=\getelemof\yytable\at\yyn\relax possible so it has to expand to a number;
% incidentally, some care should be taken using the above assignment to make sure that
% it is not followed by an expandable token (such as \if) as in this case the token might be 
% expanded prematurely while the assignment is looking for the first non-expandable token which
% is not part of the number; this is the reason for the \relax

\def\getelemof#1\at#2{% #1 is the name of the token register containing the array, #2 is the index
    \expandafter\get@l@mof\expandafter{\csname#1\endcsname}{#2}% 
}

\def\get@l@mof#1#2{%
    \expandafter\get@lemof\expandafter{\the#1}{#2}%
}

\def\get@lemof#1#2{% 
    \ifcase#2 #1\else\fi
}

\let\fgetelemof\getelemof

% token register access

\def\concat#1#2{% store the concatenation result in the first sequence
    #1\expandafter\expandafter\expandafter{\expandafter\the\expandafter#1\the#2}%
}

\def\concatl#1#2{% store the concatenation result in the second sequence
    \expandafter\conc@tl\expandafter{\the#2}{#1}{#2}%
}

\def\conc@tl#1#2#3{%
    #3\expandafter{\the#2#1}%
}

\def\appendr#1#2{%
    \begingroup
        \edef\next{#1{\the#1#2}}\next
    \tokreturn{}{}{#1{\the#1}}%
}

\def\appendl#1#2{%
    \begingroup
        \edef\next{#1{#2\the#1}}\next
    \tokreturn{}{}{#1{\the#1}}%
}

% appending to token registers without expansion

\long\def\appendlnx#1#2{%
    \expandafter\app@ndlnx\expandafter{\the#1}{#2}{#1}%
}

\long\def\app@ndlnx#1#2#3{%
    #3{#2#1}%
}

% one can use #1\expandafter{\the#1#2} instead of \appendrnx below;
% this form (as well as the \appendlnx above) has the advantage of 
% being useable with \romannumeral0 in case one merely wants to record 
% the concatenation for future use

\long\def\appendrnx#1#2{%
    \expandafter\app@ndrnx\expandafter{\the#1}{#2}{#1}%
}

\long\def\app@ndrnx#1#2#3{%
    #3{#1#2}%
}

% a macro to append new material to an existing control sequence

\def\appendxrt#1#2#3#4{% #1 one of \def, \edef (why?), \gdef, \xdef (why?)
                       % #2 sequence name being appended to
                       % #3 the material appended to the right (expanded once)
                       % #4 the material appended to the right of #3 (not expanded)
    \expandafter\app@ndxrt\expandafter{\csname #2\endcsname}{#1}{#3}{#4}%
}

\def\app@ndxrt#1#2#3#4{% #1 is the sequence being appended to
                       % #2 is \?def
                       % #3 is expanded once (appended to the right of #1)
                       % #4 is appended to the right of #3 (not expanded)
    \expandafter\ap@@ndxrt\expandafter{#3}{#4}{#2}{#1}%
}

\def\ap@@ndxrt#1#2#3#4{% #1 is expanded once (appended to the right of #4)
                       % #2 is appended to the right of #1 (not expanded)
                       % #3 is \?def
                       % #4 is the sequence being appended to
    \expandafter#3\expandafter#4\expandafter{#4#1#2}%
}

% the following macros are an expandable way to determine if a token register is empty;
% while a number of different conditionals can be used, including plain \iffalse,
% this choice seems to result in a shortest macro and the fewest number of \expandafter's; 
% an idea from
%    http://tex.stackexchange.com/questions/2936/test-whether-token-list-is-empty
% where it is attributed to Ulrich Diez can be generalized to apply multiple tests inside braces
% in a row; the macros from that discussion are quoted below; note, however, that these macros 
% lead to unbalanced braces inside alignments (see The \TeX book, Appendix~D, p.~385 for the 
% discussion of the `master counter' and the `balance counter' and their behavior when
% \TeX\ evaluates the constants `{ and `}); in addition, the first `1' is superfluous;

%\newcommand\@ifempty@toks[1]{%
%  \ifcase\iffalse{{{\fi\expandafter\@ifempty@@toks\the#1}1}1}0
%    \expandafter\@firstoftwo
%  \else
%    \expandafter\@secondoftwo
%  \fi}
%\newcommand{\@ifempty@@toks}
%  {\expandafter\@gobble\expandafter{\expandafter{%
%        \ifcase`}\expandafter}\expandafter\fi\string}

% as a note of explanation, the reason this works relies on the fact
% that \string will turn a `{', a `}', or any other token into a
% non-brace while the parameter scanning mechanism of \TeX\ will try
% to collect the smallest possible balanced input; the `excessive'
% braces will disappear in the expansion of the `\if...' construct;
% the reason \if or other macros that expand their arguments are so
% well suited for this `chain expansion' mechanism is in the fact
% that the expansions for \string and \if... are launched from the
% same point.

\long\def\yytoksempty#1{%
    \iffalse{{\fi
    \if{\expandafter\yytoks@mpty\the#1}}}%
        \yybreak\yyfirstoftwo
    \else
        \yybreak\yysecondoftwo
    \yycontinue
}

% when the token list is empty, \TeX\ will try to expand \yybreak premaurely;
% in this case \yybreak forces a \fi to be expanded while skipping the rest;
% note that a simple \expandafter would not work in this case as \TeX would 
% insert a \relax when trying to expand a premature \else (this can be only
% gleaned from `\TeX\ the program')

\long\def\yystringempty#1{%
    \iffalse{{\fi
    \if{\yytoks@mpty#1}}}%
        \yybreak\yyfirstoftwo
    \else
        \yybreak\yysecondoftwo
    \yycontinue
}

\catcode`\>=2

\def\yytoks@mpty{%
    \expandafter\eatone\expandafter{\expandafter{%
        \if}\expandafter>\expandafter\fi\string
}

\catcode`\>=12

\long\def\yystartsinspace#1{% is the first token a \charcode 32, \catcode 10 token?
    \iffalse{\fi\yystartsinspac@#1 }%
}

\long\def\yystartsinspac@#1 {%
    \yystringempty{#1}%
        {\expandafter\yysecondofthree\expandafter{\string}}%
        {\expandafter\yythirdofthree\expandafter{\string}}%
}

% the macro below can be simplified by reducing the number of braces
% but then \yytoks@mpty could not be reused

\long\def\yystartsinbrace#1{%
    \iffalse{\fi
    \if{\yytoks@mpty#1}}%
        \yybreak\yysecondoftwo
    \else
        \yybreak\yyfirstoftwo
    \yycontinue
}

% the macros below are based on David Kastrup's magnificent string comparison 
% macros:
%    \def\strequal#1{\number\strequalstart{}{}#1\relax}
%    \def\strequalstart#1#2#3{\if#3\relax\strequalstop\fi
%      \strequalstart{\if#3#1}{#2\fi}}
%    \def\strequalstop\fi\strequalstart#1#2#3{\fi#1#3\relax'#213 }
%
%    use: \if\strequal{string}{string}...
%
% they were adjusted to handle spaces inside the strings and to conform to a different
% syntax, namely \yyifsamestring{string1}{string2}{true}{false}
% the original macros use the fact that, say \if1\fi will expand to nothing and
% that \number'13 expands to 11 whereas \number13 expands to 13; the elegance of
% the second test was lost due to a different syntax;

\edef\yyifsamestring#1{\noexpand\yyifsamestr@ng{}{}#1 \noexpand\yyifsam@str@ng\space}
\def\yyifsamestr@ng#1#2#3 {\ifx\yyifsam@str@ng#3\yyifsam@str@ng\fi
    \yyifs@m@str@ng{#1}{#2}#3\space}

\def\yyifs@m@str@ng#1#2#3{%
    \if#3\space
        \expandafter\yyifsamestr@ng
    \else
        \expandafter\yyifs@m@str@ng
    \fi
    {\if#3#1}{#2\fi}%
}

\def\yyifsam@str@ng\fi\yyifs@m@str@ng#1#2\yyifsam@str@ng\space#3{\fi
    \if\noexpand\yyifsam@str@ng#1#3 \noexpand\yyifsam@str@ng\yystrcleanup#2\fi
    \yysecondoftwo
}

\def\yystrcleanup#1\yysecondoftwo{#1\yyfirstoftwo}

% prefix comparison macros
% use: \romannumeral-0\yyprefixmatch{string1}{string2}
% this will expand into {common prefix}{rest of string1}{rest of string2}

\def\yyprefixmatch#1#2{%
    \yyprefixmatchbegin{#1\end}{#2\relax}{}%
}

\def\yyprefixmatchbegin#1#2{%
    \yypr@fixmatch#1{#2}%
}

\def\yypr@fixmatch#1#2#{%
    \yypr@fixm@tch{#1}{#2}%
}

\def\yypr@fixm@tch#1#2#3{% #2 is the rest of string1, #1 is the first char of string1
    \yyprefixrematch#3{#1}{#2}%
}

\def\yyprefixrematch#1#2#{%
    \yypr@fixrematch{#1}{#2}%
}

\def\yypr@fixrematch#1#2#3#4#5{%
    \ifx#1#3%
        \yybreak{\yyprefixmatchbegin{#4}{#2}{#5#1}}%
    \else
        \yybreak{\yyprefixmatchend{#3#4}{#1#2}{#5}}%
    \yycontinue
}

\def\yyprefixmatchend#1#2#3{%
    \yypr@fixmatchend#1#2{#3}%
}

\def\yypr@fixmatchend#1\end#2\relax#3{%
    {#3}{#1}{#2}%
}

% macros to check if the string matches #1* for some char #1
% use: \yyifrepeatedchar{char}{string}{true case}{false case}

\def\yyifrepeatedchar#1#2{%
    \yyifr@peatedchar#1#2\relax
}

\def\yyifr@peatedchar#1#2{%
    \ifx#2\relax
        \yybreak{\yyfirstoftwo}% string complete, match
    \else
        \yybreak{\yyifr@p@atedchar#1#2}%
    \yycontinue
}

\def\yyifr@p@atedchar#1#2{%
    \ifx#1#2%
        \yybreak{\yyifr@peatedchar#1}% next character
    \else
        \yybreak{\yyifrepeatedcharmismatch}%
    \yycontinue
}

\def\yyifrepeatedcharmismatch#1\relax{%
    \yysecondoftwo
}

% end prefix comparison macros

% a test to determine whether the argument is a given control sequence

\long\def\yyisthiscs#1#2{%
    \yystringempty{#1}{\yysecondoftwo}{%
        \yystartsinspace{#1}{\yysecondoftwo}{%
            \yystartsinbrace{#1}{\yysecondoftwo}{%
                \expandafter\yystringempty\expandafter{\eatone#1}{%
                    \expandafter\yyisth@scs\expandafter{\string#1}{#2}%
                }{\yysecondoftwo}%
            }
        }
    }%
}

\long\def\yyisth@scs#1#2{%
    \expandafter\yyifsamestring\expandafter{\string#2}{#1}%
}

% same as above but the argument is a token register

\def\yyisthiscsr#1{%
    \expandafter\yyisthiscs\expandafter{\the#1}%
}

% a `self-propagating \expandafter'; allows building lists like \yysx a\yysx b ...
% so that a \romannumeral-1 at the beginning of the list would cary the expansion
% to the last token but leave the list intact; note that #1 should be a single token

\def\yysx#1#2{%
    \expandafter\space\expandafter\yysx\expandafter#1\romannumeral-1#2%
}

% linked list macros

\newif\iftracinglists

\def\initlist#1{% #1 is the list name
    \iftracinglists
         \message{init list<#1>}%
    \fi
    \expandafter\def\csname list.counter(#1)\endcsname{0}% init the counter
    \resetlistpointer{#1}%
}

\def\resetlistpointer#1{%
    \iftracinglists
         \message{reset list pointer<#1>}%
    \fi
    \expandafter\def\csname list.pointer(#1)\endcsname{0}% init the pointer
}

% the macro below may fail on some potential elements (the ones that contain #'s);
% for extra robustness one may use \appendtolistx after storing the list element in
% a token register.
% if the list implementation changes, \splitlist@t must change too

\def\appendtolistg#1#2#3{% #1 is the list name
                         % #2 is the list element
                         % #3 is the action on the contents
    % store the contents in the inner element
    \expandafter#3\csname list.term.1(#1)[\csname list.counter(#1)\endcsname]\endcsname{ #2}%
    \iftracinglists
        {\edef\lname{#1}\toksa\expandafter\expandafter\expandafter
            {\csname list.term.1(#1)[\csname list.counter(#1)\endcsname]\endcsname}%
        \message{adding to list<#1> at \showlistcounter{\lname}::\the\toksa.}}%
    \fi
    {%
        \edef\listname{#1}%
        \tempca\csname list.counter(\listname)\endcsname\relax
        % outer element name
        \toksa\expandafter{\csname list.term.0(\listname)[\the\tempca]\endcsname}%
        % inner element name
        \toksb\expandafter{\csname list.term.1(\listname)[\the\tempca]\endcsname}%
        \advance\tempca by\@ne
        % next outer element name
        \toksc\expandafter{\csname list.term.0(\listname)[\the\tempca]\endcsname}%
        \edef\next{%
            % store the new counter
            \def\expandafter\noexpand\csname list.counter(\listname)\endcsname{\the\tempca}%
            % wrap the inner element
            \def\the\toksa{\noexpand\expandafter\the\toksb\noexpand\romannumeral0\the\toksc}%
        }\expandafter
    }\next % \next is not affected by this
}

\def\appendtolist#1#2{\appendtolistg{#1}{#2}{\def}}
\def\appendtolistx#1#2{\appendtolistg{#1}{#2}{\edef}}
\def\appendtolisti#1#2{\appendtolistg{#1}{#2}{\fdef}}

% note that lists with \listiterator entries can be executed and spliced
% but some functions (like \replace...) below do not work properly

\def\fdef#1#2{%
    \def#1{\listiterator{#1}{#2}}% so that #1 knows its name ...
}

\def\listiteratorsimple#1#2{%
    #2%
}

\let\listiterator\listiteratorsimple % expand the list without preprocessing

% the name of the next macro is misleading: the whole
% concatenated list starts at the first term of list #1
% but the only way to append to the resulting list is to append to
% list #2; any attempt to append a term to list #1 will
% disconnect the lists (although they can be concatenated again)

\def\concatlists#1#2{%
    \expandafter\expandafter\expandafter
    \let\expandafter\expandafter
        \csname list.term.0(#1)[\csname list.counter(#1)\endcsname]\endcsname
        \csname list.term.0(#2)[0]\endcsname
}

\def\listisempty#1{%
    \ifnum\csname list.counter(#1)\endcsname=\z@
        \yybreak\yyfirstoftwo
    \else
        \yybreak\yysecondoftwo
    \yycontinue
}

% execute a slice of a list (commonly amended by an iterator)

\def\evallistbetween#1#2#3{% #1 is the list name
                           % #2 is the start marker
                           % #3 is the finish marker
    \ifnum#3<#2\relax
        \yybreak{}%
    \else
        \yybreak{%
                \expandafter\expandafter\expandafter\@vallistbetween\csname list.term.0(#1)[#3]\endcsname{#1}{#2}{#3}%
        }%
    \yycontinue
}

\def\@vallistbetween#1#2#3#4#5#6#7#8{% #1 \expandafter                                                   
                                       % #2 the contents of the element at #6                              
                                       % #3 \romannumeral                                                  
                                       % #4 0                                                              
                                       % #5 the next element in the remaining list                                   
                                       % #6 the list name                                                  
                                       % #7 the start marker
                                       % #8 the finish marker
    \expandafter\edef\csname list.term.0(#6)[#8]\endcsname{%
        \noexpand#1\noexpand#2\noexpand#3#4\noexpand\space  
    }% terminate the list temporarily
    \executelistat{#6}{#7}% execute the list slice
    \expandafter\edef\csname list.term.0(#6)[#8]\endcsname{%
        \noexpand#1\noexpand#2\noexpand#3#4\noexpand#5%  
    }% restore the list
}

% the macro below cannot be used with iterator amended lists (unless the iterator
% is purely expandable)

\def\readlistbetween#1#2#3\to#4{% #1 is the list name
                                % #2 is the start marker
                                % #3 is the finish marker
                                % #4 is name of the token register
    \ifnum#3<#2\relax
        %\errmessage{trying to read a negative slice (#2->#3) in list #1}%
        #4{}%
    \else
        \expandafter\expandafter\expandafter\r@adlistbetween\csname list.term.0(#1)[#3]\endcsname{#1}{#2}{#3}{#4}%    
    \fi
}

\def\r@adlistbetween#1#2#3#4#5#6#7#8#9{% #1 \expandafter                                                   
                                       % #2 the contents of the element at #6                              
                                       % #3 \romannumeral                                                  
                                       % #4 0                                                              
                                       % #5 the next element in the remaining list                                   
                                       % #6 the list name                                                  
                                       % #7 the start marker
                                       % #8 the finish marker
                                       % #9 the token register
    \expandafter\edef\csname list.term.0(#6)[#8]\endcsname{%
        \noexpand#1\noexpand#2\noexpand#3#4\noexpand\space  
    }% terminate the list temporarily
    #9\expandafter{\romannumeral0\executelistat{#6}{#7}}% store the list slice
    \expandafter\edef\csname list.term.0(#6)[#8]\endcsname{%
        \noexpand#1\noexpand#2\noexpand#3#4\noexpand#5%  
    }% restore the list
}

\def\consumelistupto#1#2\to#3{%
    \readlistbetween{#1}{\showlistpointer{#1}}{#2}\to{#3}%
    {%
        \iftracinglists
            \message{splice<#1> (\csname list.pointer(#1)\endcsname,#2)}%
        \fi
        \tempca=#2\relax
        \advance\tempca\@ne
        \ifnum\tempca>\showlistpointer{#1}\relax
            \edef\next{\def\expandafter\noexpand\csname list.pointer(#1)\endcsname{\the\tempca}}%
        \else
            \let\next\empty
        \fi
        \expandafter
    }\next
}

\def\consumefulllist#1\to#2{%
    #2\expandafter{\romannumeral0\executelistat{#1}{\showlistpointer{#1}}}%
}

% the macro below is not aware of the list iterators so it should be used carefully with amended lists
% (one possible way is to redefine the list iterator before applying this macro).

\def\changelistelem#1#2#3#4{% #1 list name                          
                            % #2 marker     
                            % #3 prefix                         
                            % #4 suffix                                
    \expandafter\ch@ngelistelem\csname list.term.1(#1)[#2]\endcsname{#3}{#4}%
}

\def\ch@ngelistelem#1#2#3{
    \expandafter\ch@ng@listelem\expandafter{#1}#1{#2}{#3}%
}

\def\ch@ng@listelem#1#2#3#4{% remove the space added by the list packaging macros
    \expandafter\ch@ng@l@stelem\expandafter{\romannumeral0#1}{#2}{#3}{#4}%
}

\def\ch@ng@l@stelem#1#2#3#4{% assemble everything
    \def#2{ #3#1#4}%
}

\def\replacelistelemg#1#2#3#4{% #1 list name
                              % #2 marker
                              % #3 new contents
                              % #4 action (\def, \edef, etc.)
    \expandafter\expandafter\expandafter\r@placelistelem\csname list.term.0(#1)[#2]\endcsname{#1}{#2}%
    \expandafter#4\csname list.term.1(#1)[#2]\endcsname{#3}%
}

\def\r@placelistelem#1#2#3#4#5#6#7{% #1 \expandafter                                                  
                                   % #2 the contents of the element at #7                           
                                   % #3 \romannumeral                                                 
                                   % #4 0                                                             
                                   % #5 the next element in the list                                  
                                   % #6 the list name                                                 
                                   % #7 the marker
    \expandafter\edef\csname list.term.0(#6)[#7]\endcsname{\noexpand\expandafter
        \expandafter\noexpand\csname list.term.1(#6)[#7]\endcsname
        \noexpand\romannumeral0\noexpand#5}%                                                 
}

\def\replacelistelem#1#2#3{%
    \replacelistelemg{#1}{#2}{#3}{\def}%
}

\def\replacelistelemx#1#2#3{%
    \replacelistelemg{#1}{#2}{#3}{\edef}%
}

% the next macro assumes that the list counter is pointing to the last (currently empty)
% list element

\def\finishlist#1{% #1 is the list name
    \expandafter\def\csname list.term.0(#1)[\showlistcounter{#1}]\endcsname{ }%
}

\def\executelistat#1#2{% #1 is the list name
                       % #2 is the element at which to start execution
    \csname list.term.0(#1)[#2]\endcsname
}

\def\executelist#1{% #1 is the list name
    \romannumeral0\executelistat{#1}{0}%
}

\def\storelist#1\to#2{% #1 is the list name
                      % #2 is the token register to store it in
    #2\expandafter{\romannumeral0\csname list.term.0(#1)[0]\endcsname}%
}

\def\storelistx#1\to#2#3{% #1 is the list name
                         % #2 is the token register to store it in
                         % #3 is the suffix
    #2\expandafter{\romannumeral0\csname list.term.0(#1)[0]\endcsname#3}%
}

\def\showlistcounter#1{%
    \number\csname list.counter(#1)\endcsname
}

\def\showlistpointer#1{%
    \number\csname list.pointer(#1)\endcsname
}

\def\showlistcs#1{%
    {\toksa\expandafter{\csname list.term.0(#1)[\csname list.counter(#1)\endcsname]\endcsname}%
     \toksb\expandafter\expandafter\expandafter{\the\toksa}%
    \message{current cs: \the\toksa is \the\toksb}}%
}

% use example for the macros above:
%\initlist{table}
%\toksa{#}
%\appendtolistx{table}{\the\toksa,}
%\appendtolist{table}{a,}
%\appendtolist{table}{b,}
%\appendtolist{table}{{c},}
%\appendtolist{table}{d,}
%\appendtolist{table}{e,}
%\appendtolist{table}{{f}}
%\appendtolist{table}{\space.}
%\appendtolistx{table}{\space\space\end}
%\finishlist{table}
%\storelist{table}\to\toksa
%\errmessage{full list: \the\toksa}

% use example for the macros above:
%\initlist{table}
%\toksa{#}
%\def\listiteratorxmpl#1#2{%
%    #2{\format}%
%}
%\let\listiterator\listiteratorxmpl
%\appendtolisti{table}{..}
%\appendtolisti{table}{a,}
%\appendtolisti{table}{b,}
%\appendtolisti{table}{{c},}
%\appendtolisti{table}{d,}
%\appendtolisti{table}{e,}
%\appendtolisti{table}{{f}}
%\appendtolisti{table}{.}
%\appendtolisti{table}{\end}
%\finishlist{table}
%\storelist{table}\to\toksa
%\errmessage{full list: \the\toksa}

% `data structure access' macros: picking the n-th undelimited parameter
% in a parameter list inside a token register
% it is assumed that none of the arguments is \end, and that there are enough
% parameters to pick the desired one

\def\getfirst#1\to#2{%
    #2\expandafter\expandafter\expandafter{\expandafter\g@tfirst\the#1\end}%
}

\def\g@tfirst#1#2\end{#1}

\def\getsecond#1\to#2{%
    #2\expandafter\expandafter\expandafter{\expandafter\g@tsecond\the#1\end}%
}

\def\g@tsecond#1#2#3\end{#2}

\def\getthird#1\to#2{%
    #2\expandafter\expandafter\expandafter{\expandafter\g@tthird\the#1\end}%
}

\def\g@tthird#1#2#3#4\end{#3}

\def\getfourth#1\to#2{%
    #2\expandafter\expandafter\expandafter{\expandafter\g@tfourth\the#1\end}%
}

\def\g@tfourth#1#2#3#4#5\end{#4}

\def\getfifth#1\to#2{%
    #2\expandafter\expandafter\expandafter{\expandafter\g@tfifth\the#1\end}%
}

\def\g@tfifth#1#2#3#4#5#6\end{#5}

\def\getsixth#1\to#2{%
    #2\expandafter\expandafter\expandafter{\expandafter\g@tsixth\the#1\end}%
}

\def\g@tsixth#1#2#3#4#5#6#7\end{#6}

\def\getseventh#1\to#2{%
    #2\expandafter\expandafter\expandafter{\expandafter\g@tseventh\the#1\end}%
}

\def\g@tseventh#1#2#3#4#5#6#7#8\end{#7}

\def\geteightth#1\to#2{%
    #2\expandafter\expandafter\expandafter{\expandafter\g@teightth\the#1\end}%
}

\def\g@teightth#1#2#3#4#5#6#7#8#9\end{#8}

\def\getninth#1\to#2{% the `.' is necessary since \TeX's scanning mechanism will
                     % strip any potential braces surrounding the last parameter
                     % (assuming there are exactly nine) twice:
                     %  o first, expanding \g@tninth,
                     %  o second, expanding \g@tfirst
    #2\expandafter\expandafter\expandafter{\expandafter\g@tninth\the#1.\end}%
    #2\expandafter\expandafter\expandafter{\the#2}%
}

\def\g@tninth#1#2#3#4#5#6#7#8#9\end{\g@tfirst#9\end}

\def\gettenth#1\to#2{% no need for `.' (or any other placeholder) here,
                     % since the #9-th parameter to \g@ttenth is a list of
                     % at least two parameters itself, thus any existing braces
                     % have survived intact
    #2\expandafter\expandafter\expandafter{\expandafter\g@ttenth\the#1\end}%
    #2\expandafter\expandafter\expandafter{\the#2}%
}

\def\g@ttenth#1#2#3#4#5#6#7#8#9\end{\g@tsecond#9\end}

% removing the first element of a token register if it has more than one;

\def\sansfirst#1{%
    \expandafter\s@nsfirst\expandafter{\the#1}{#1}%
}

\def\s@nsfirst#1#2{%
    \expandafter\s@nsf@rst\expandafter{\eatone#1}{#2}%
}

\def\s@nsf@rst#1#2{%
    \yystringempty{#1}{}{%
        #2{#1}%
    }%
}

% a version of the macro above that expands to the original argument with the first element removed

\def\sansfirstx#1{%
    \expandafter\yystringempty\expandafter{\eatone#1}{#1}{\eatone#1}%
}

% string replacement: all arguments are registers, nothing is expanded, no \next is defined
% note that this is not a greedy replacement: this could be arranged with a more sophisticated macro
% also note that the string being replaced cannot have any braces in it

\newif\ifyytracereplacements
\newif\ifyyreplaced

\yytracereplacementstrue

\def\yyreplacestring#1\in#2\with#3{%
      \expandafter\def\expandafter\r@placestring\expandafter##\expandafter1\the#1##2\end{%
          \def\r@placestring{##2}% is this the string at the very end?
          \ifx\r@placestring\empty % then it is the one we inserted,
                                   % report
              \yyreplacedfalse
              \ifyytracereplacements
                  \errmessage{string <\the#1> not present in \the#2}% do not change the register if the string is not there
              \fi
          \else % remove the extra copy of #1\end at the end
              \yyreplacedtrue
              \expandafter#2\expandafter\expandafter\expandafter
                  {\expandafter\r@plac@string\expandafter{\the#3}{##1}##2\end}%
      \fi}% end of \r@placestring definition
      \expandafter\def\expandafter\r@plac@string
          \expandafter##\expandafter1%
          \expandafter##\expandafter2%
          \expandafter##\expandafter3%
          \the#1\end{##2##1##3}%
      \expandafter\expandafter\expandafter\r@placestring\expandafter\the\expandafter#2\the#1\end
}

% returning token register values from a group
% in such a way that no other register values are affected

\def\tokreturn#1#2#3{% #1 is the code to be prepended (will be expanded)
                     % #2 is a list of token registers
                     % #3 is the code to be appended
    \t@kreturn{#1}{#3}#2\end
}

\def\t@kreturn#1#2#3{% first step: see if the list is non-empty and pick the first token register
    \ifx#3\end % there are no registers to return so \toksa can be used as temporary storage
               % (on exiting the current \begingroup its value will be restored to what it was
               % before the group was entered)
        \edef\next{\toksa{#1#2}}\next % return prepended and appended code
        \def\t@kreturn{\expandafter\endgroup\the\toksa}%
    \else
        \edef\tokreturn{#3{{#2}#1#3{\the#3}}}\tokreturn
        \let\tokreturn#3%
        \let\t@kreturn\t@kr@turn
    \fi
    \t@kreturn % this sequence will be restored to its original value when the group is exited
}

\def\t@kr@turn#1{%
    \ifx#1\end
        \def\t@kreturn##1##2\end{\tokreturn{##2##1}}%
        \expandafter\t@kreturn\the\tokreturn\end
        \def\t@kreturn{\expandafter\endgroup\the\tokreturn}%
    \else
        \edef\t@kreturn{\tokreturn{\the\tokreturn#1{\the#1}}}\t@kreturn
        \let\t@kreturn\t@kr@turn
    \fi
    \t@kreturn
}

% switch macros, also used to implement state machines
% a lot of care has been taken to ensure that no control sequence is changed
% as well as all the register values are preserved.

\newif\iftracedfa

\def\taction#1\in#2{%
    \begingroup
        \edef\acstring{#1}% in case #1 is, say, \the\toksa, so we no longer have to keep track of it
        \iftracedfa\ferrmessage{acting on <\meaning\acstring>\space in (\string#2) \getstatename#2 }\fi
        \toksa\expandafter{#2}\toksb\expandafter{\acstring}%
        \edef\next{\toksa{\the\toksa\the\toksb{%
                                        \iftracedfa\noexpand\ferrmessage{default action: \noexpand\meaning\noexpand\default}\fi
                                        \noexpand\default}}%
                    \def\noexpand\next####1\the\toksb####2####{\noexpand\grabaction}}\next
        \expandafter\next\the\toksa\grabaction
    \tokreturn{}{}{\the\toksa}%
}

\def\tactionx#1\in#2{% exclusive version of the macro above (i.e. match the last action before the brace)
    \begingroup
        \edef\acstring{#1}% in case #1 is, say, \the\toksa, so we no longer have to keep track of it
        \iftracedfa\errmessage{acting on <\meaning\acstring>\space in (\string#2) \getstatename#2 }\fi
        \toksa\expandafter{#2}\toksb\expandafter{\acstring}%
        \edef\next{\toksa{\the\toksa\the\toksb{%
                                        \iftracedfa\noexpand\ferrmessage{default action: \noexpand\meaning\noexpand\default}\fi
                                        \noexpand\default}}%
                    \def\noexpand\next####1\the\toksb####{\noexpand\grabaction}}\next
        \expandafter\next\the\toksa\grabaction
    \tokreturn{}{}{\the\toksa}%
}

\def\getstatename#1{\expandafter\g@tstatename#1.\raw}

\def\g@tstatename#1#2\raw{\expandafter\eatone\string#1}

\def\caction#1\in#2{%
    \begingroup
        \uccode`.=#1\relax
        \uppercase{\toksa{\taction{.}\in}}%
        \toksb{#2}\concat\toksa\toksb
    \tokreturn{}{}{\the\toksa}%
}

\def\checkforcount#1{% a rough implementation of `type checking' for a parameter
    \expandafter\expandafter\expandafter
        \ch@ckforcount\expandafter\meaning\expandafter#1\meaning\count\end
}

\expandafter\def\expandafter\ch@ckforcount\expandafter#\expandafter1\meaning\count#2\end{%
    \yystringempty{#2}{\toksa{\taction}}{\toksa{\caction}}%
}

\def\switchonwithtype#1\in#2{%
    \begingroup
        \checkforcount#1%
        \toksb{{#1}\in{#2}}\concat\toksa\toksb
    \tokreturn{}{}{\the\toksa}%
}%

\let\switchon\taction
\let\default\relax

\def\grabaction#1#2\grabaction{\toksa{#1}}

% switch manipulation macros: adding and replacing labels and actions
% the macros assume that the switch to be manipulated is well formed, otherwise
% no assumptions have been made;
% if the label is not present in the switch or the new label already exists, an
% error is returned
% the macros are not expandable but can be made such with some
% (rather significant) effort

% #1 is the name of the old switch
% #2 is the existing label to which the new label will be added
% #3 is the new label
% #4 is the name of the new switch
% #5 is the operation to perform if #2 is present and #3 is not
%    this operation takes the following parameters:
%        #1: the expanded original switch
%        #2: the existing label
%        #3: the new label
%        #4: the name of the new switch
\def\matchswitch#1#2#3#4#5{%
    \expandafter\matchswitch@a\expandafter{#1}{#2}{#3}{#4}{#1}{\matchswitch@e}{#5}%
}

% #1 is the expanded version of the switch
% #2 is the label at which to change
% #3 is the new label
% #4 is the name of the new switch
% #5 is the switch
% #6 is the test sequence to apply if #2 is present
% #7 is the operation to perform if #2 is present and #3 is not
\def\matchswitch@a#1#2#3#4#5#6#7{\matchswitch@b{#1}{#1}{#2}{#3}{#4}{#5}{#6}{#7}}

% #1 is the expanded version of the switch
% #2 is the expanded version of the switch
% #3 is the label at which to change
% #4 is the new label
% #5 is the name of the new switch
% #6 is the switch
% #7 is the test sequence to apply if #3 is present
% #8 is the operation to perform if #3 is present and #4 is not
\def\matchswitch@b#1#2#3#4#5#6#7#8{%
    \def#5##1#3{\matchswitch@c}%
    \expandafter\expandafter\expandafter#5\expandafter\eatone\string{#1#3}{#2}{#3}{#4}{#5}{#6}{#7}{#8}%
}

\def\matchswitch@c{%
    \expandafter\expandafter\expandafter\matchswitch@d
        \expandafter\expandafter\expandafter{\expandafter\eatone\string}%
}

% #1 is the match result
% #2 is the expanded version of the switch
% #3 is the label at which to change
% #4 is the new label
% #5 is the name of the new switch
% #6 is the switch
% #7 is the test sequence to apply if #3 is present
% #8 is the operation to perform if #3 is present and #4 is not
\def\matchswitch@d#1#2#3#4#5#6#7#8{%
    #7{#1}{#2}{#3}{#4}{#5}{#6}{#8}%
}

% #1 is the match result
% #2 is the expanded version of the switch
% #3 is the label at which to change
% #4 is the new label
% #5 is the name of the new switch
% #6 is the switch
% #7 is the operation to perform if #3 is present and #4 is not
\def\matchswitch@e#1#2#3#4#5#6#7{%
    \yystringempty{#1}{% label not present
        \errhelp{Switch #6 contents: #2}%
        \errmessage{label \nx#3 was not found in switch \nx#6}%
    }{%
        \yystringempty{#4}{% no new label, skip the next test
            #7{#2}{#3}{#4}{#5}%
        }{%
            \matchswitch@a{#2}{#4}{#3}{#5}{#6}{\matchswitch@f}{#7}%
        }%
    }%
}

\def\matchswitch@f#1#2#3#4#5#6#7{%
    \yystringempty{#1}{% (new) label not present
        #7{#2}{#4}{#3}{#5}%
    }{%
        \errhelp{Switch #6 contents: #2}%
        \errmessage{label \nx#3 already exists in switch \nx#6}
    }%
}

% add a new empty action to a switch with a known action (safety feature)

\def\amendswitch#1\near#2\by#3\to#4{%
    \matchswitch{#1}{#2}{#3}{#4}{\@mendswitch}%
}

\def\@mendswitch#1#2#3#4{%
    \def#4{#1#3{}}%
}

% add a label to an existing action

\def\extendswitch#1\at#2\by#3\to#4{%
    \matchswitch{#1}{#2}{#3}{#4}{\@xtendswitch}%
}

\def\@xtendswitch#1#2#3#4{%
    \def#4##1#2##2#3{\def#4{##1#2#3##2}}%
    #4#1#3%
}

% replace an existing label inside a switch

\def\replaceswitch#1\at#2\by#3\to#4{%
    \matchswitch{#1}{#2}{#3}{#4}{\r@placeswitch}%
}

\def\r@placeswitch#1#2#3#4{%
    \def#4##1#2##2#3{\def#4{##1#3##2}}%
    #4#1#3%
}

% replace an existing action inside a switch
% this can also be used to add new labels, although no check is performed
% whether the new label already exists
% a word of caution: if one is using this command as intended, the
% action code should be surrounded by an additional pair of braces (see
% a use example in yy.sty)

\def\replaceaction#1\at#2\by#3\to#4{%
    \matchswitch{#1}{#2}{}{#4}{\r@placeaction{#3}}%
}

% #1 holds the new action
% #2 is the expanded switch
% #3 is the label at which to make the replacement
% #4 is empty
% #5 is the name of the new switch
\def\r@placeaction#1#2#3#4#5{%
    \r@placeaction@a{#2}{#3}{#5}{#1}%
}

% #1 is the expanded switch
% #2 is the label at which to make the replacement
% #3 is the name of the new switch
% #4 is the new action
\def\r@placeaction@a#1#2#3#4{%
    \def#3##1#2##2##{\expandafter\expandafter\expandafter
        \r@placeaction@b\expandafter\expandafter\expandafter{\expandafter\eattwo\string}}%
    \expandafter\expandafter\expandafter#3\expandafter\eatone\string{#1}{#2}{#3}{#1}{#4}%
}

% #1 is the part of the switch after the action
% #2 is the label at which to make the replacement
% #3 is the name of the new switch
% #4 is the expanded switch
% #5 is the new action
\def\r@placeaction@b#1#2#3#4#5{%
    \def#3##1#2##2##{\expandafter\expandafter\expandafter
        \r@placeaction@c\expandafter\expandafter\expandafter{\expandafter\eatone\string}{##1}{##2}}%
    \expandafter\expandafter\expandafter#3\expandafter\eattwo\string{#4.}{#2}{#3}{#1}{#5}%
}

% #1 = {{before the label}{between the label and the action} after the action . }
\def\r@placeaction@c#1{%
    \expandafter\yystringempty\expandafter{\r@placeaction@f#1}{% the remainder of the switch is gone
        \expandafter\r@placeaction@d\r@placeaction@e#1%
    }{%
        \expandafter\r@placeaction@c\expandafter{\r@placeaction@e#1}%
    }
}

% #1 before the label
% #2 between the label and the action
% #3 is the label
% #4 is the name of the new switch
% #5 part of the switch after the action
% #6 is the new action
\def\r@placeaction@d#1#2#3#4#5#6{\def#4{#1#3#2#6#5}}

\def\r@placeaction@e#1#2#3.{{#1}{#2}}

\def\r@placeaction@f#1#2#3.{}

% grab the first token unless it is a space or a brace

\def\getfirsttoken#1{%
    \yystartsinbrace{#1}{ }{\yystartsinspace{#1}{ }{%
        \expandafter\g@tfirsttoken\string{#1} % terminate \romannumeral
    }}%
}

\def\g@tfirsttoken#1#2{%
    \expandafter\noexpand\expandafter#2\romannumeral0\expandafter\eatone\expandafter{\string}%
}

% macros for `breaking out of' conditionals:
% the idea is probably folklore;
% \yybreak ... \yycontinue are the most efficient as they read everything exactly once
% and expand only what is necessary; the next preferred way is the \xskip ... series
% the \yyfinish macro is here `to plug a hole' when it is stylistically preferable
% to keep the existing conditional structure and efficiency is not that important

\long\def\xskiptofi#1#2\fi{\fi#1}
\long\def\xskiptofifi#1#2\fi\fi{\fi\fi#1}
\long\def\xskiptofififi#1#2\fi\fi\fi{\fi\fi\fi#1}

\long\def\yyfinish#1#2\yycontinue{#2#1}% here just for completeness, use the ones below instead
\long\def\yybreak#1#2\yycontinue{\fi#1}
\long\def\yybreak@#1#2\yycontinue{\fi\fi#1}
\long\def\yybreak@@#1#2\yycontinue{\fi\fi\fi#1}
\long\def\yybreak@@@#1#2\yycontinue{\fi\fi\fi\fi#1}
\long\def\yybreak@@@@#1#2\yycontinue{\fi\fi\fi\fi\fi#1}

% we intentionally leave \yycontinue defined as an \errmessage
% since it should not be expanded normally;
% every conditional that uses \yybreak?{...} ... \yycontinue construct
% must have an \else clause, i.e.\ a conditional such as
% \if ab
%     \yybreak{}%
% \yycontinue
% is a bad idea as it will result in an incomplete \iffalse
%\let\yycontinue\fi
\def\yycontinue{\errmessage{\noexpand\yycontinue should never be expanded!}}
% this also makes \if...\yycontinue constructs unskippable; this can be remedied by
% adding a \fi before \yycontinue, which will not affect a properly constructed
% conditional

\long\def\yyfirstoftwo#1#2{#1}
\long\def\yysecondoftwo#1#2{#2}
\long\def\yyfirstofthree#1#2#3{#1}
\long\def\yysecondofthree#1#2#3{#2}
\long\def\yythirdofthree#1#2#3{#3}

\long\def\yypioneofthree#1#2#3{{#1}}
\long\def\yypitwoofthree#1#2#3{{#2}}
\long\def\yypithreeofthree#1#2#3{{#3}}

% macros for taking care of extra tokens

\long\def\yyid#1{#1} % this is misnamed since it may change #1 by stripping braces and spaces
\long\def\yyswap#1#2{#2#1}
\long\def\eatone#1{}
\long\def\eattwo#1#2{}
\long\def\eatthree#1#2#3{}
\long\def\eattoend#1\end{}
\long\def\eattospace#1 {}
