% Copyright 2012-2020, 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/>.

\catcode`\@=11

% 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:}}}

\def\yyreadvstack#1\upto#2{% assume that #2 > 0
    \edef\sts{\noexpand\splitstack{\number#2}{\expandafter\xincrement\expandafter{\number\toptoks}}}#1\stackend#1%
}

\long\def\splitstack#1#2#3{%
    \expandafter\def\csname$'#1\endcsname{#3}% $
    \ifnum#2<\@cclvi % we have not reached the maximum allocated number of token registers
        \expandafter\toksdef\csname$$'#1\endcsname=#2
        \toks#2{#3}%
    \fi
    \ifnum#1=\@ne %we have read the values
        \let\sts\scoopupstack
    \else
        \edef\sts{\noexpand\splitstack{\xdecrement{#1}}{\xincrement{#2}}}%
    \fi
}

\def\yypeekvstack#1\upto#2{% assume #2 > 0
    \edef\sts{\noexpand\peelstack{\number#2}{\expandafter\xincrement\expandafter{\number\toptoks}}}#1\relax%
}

\long\def\peelstack#1#2#3{%
    \expandafter\def\csname$'#1\endcsname{#3}% $
    \ifnum#2<\@cclvi % we have not reached the maximum allocated number of token registers
        \expandafter\toksdef\csname$$'#1\endcsname=#2 
        \toks#2{#3}%
    \fi
    \ifnum#1=\@ne %we have read the values
        \let\sts\eatone
    \else
        \edef\sts{\noexpand\peelstack{\xdecrement{#1}}{\xincrement{#2}}}%
    \fi
}

% macros to support new printing routines

\def\yypeeksstack#1\upto#2\withprefix#3{% assume #2 > 0
    \edef\sts{\noexpand\peelsstack{\number#2}}%
    \expandafter\def\expandafter\sts\expandafter{\sts{#3}{}}#1\relax%
}

\long\def\peelsstack#1#2#3#4{%
    \ifnum#1=\@ne %we have read the values
        #3\let\sts\eatone
    \else
        \edef\sts{\noexpand\peelsstack{\xdecrement{#1}}}%
        \expandafter\def\expandafter\sts\expandafter{\sts{#2}{#2{#4}#3}}%     
    \fi
}

% 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}%
}

% 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 macros below are a derivation of 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}

% 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%
}

% 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
}

% 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}%
}

\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}}

% (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 asignment 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

% a nestable loop

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

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

% optimization macros: currently, the level of optimization has to be consistent throughout the
% document, i.e. \optimize macros have to be called on the same arrays after loading.
% the reason is the yyfaststack.sty file that modifies the \newtable macro once for all the tables

\def\optimize#1{%
    \setoptopt{#1}%
    \tempca\z@
    \bloop
        \tempcb=\expandafter\ifcase\expandafter\tempca\the\csname#1\endcsname\else\@MM\fi\relax
        \ifnum\tempcb<\@MM %
            \expandafter\edef\csname #1\parsernamespace\the\tempca\endcsname{\the\tempcb}%
            \advance\tempca\@ne
    \repeat
}

\def\optimizetext#1{% optimizing text arrays
    \setoptopt{#1}%
    \tempca\z@
    \@ptimizetext{#1}
}

\def\@ptimizetext#1{%
    \edef\next{\expandafter\ifcase\expandafter\tempca\the\csname#1\endcsname\else\end\fi}%
    \ifx\next\endcontainer
        \let\next\eatone
    \else
        \expandafter\edef\csname #1\parsernamespace\the\tempca\endcsname{\next}%
        \advance\tempca\@ne
        \let\next\@ptimizetext
    \fi
    \next{#1}%
}

\def\uoptimize#1{% same as the macro above but produces nonnegative constants as \mathchardef's
    \setoptopt{#1}%
    \tempca\z@
    \bloop
        \tempcb=\expandafter\ifcase\expandafter\tempca\the\csname#1\endcsname\else\@MM\fi\relax
        \ifnum\tempcb<\@MM %
            \toksa\expandafter{\csname #1\parsernamespace\the\tempca\endcsname}%
            \edef\next{\mathchardef\the\toksa=\the\tempcb\relax}\next
            \advance\tempca\@ne
    \repeat
}

\def\setoptopt#1{%
    \expandafter\let\csname optopt[#1]\parsernamespace\endcsname\end
}

\countdef\toptoks=15 % register responsible for token allocations 

% 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\action#1\in#2{%
    \begingroup
        \checkforcount#1%
        \toksb{{#1}\in{#2}}\concat\toksa\toksb
    \tokreturn{}{}{\the\toksa}%
}%

\let\switchon\taction
\let\switchonwithtype\action % phase out \action, since it is a rather common name
\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 label at which to change
% #2 is the new label
% #3 is the name of the new switch
% #4 is the switch
% #5 is the operation to perform if #2 is present and #3 is not
\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}{% 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 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

\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

% macros for taking care of extra tokens

\long\def\yyid#1{#1} % this is misnamed since it changes #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 {}

\input xarithm.sty

\newif\ifbootstrapmode
