% 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 . \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