diff options
Diffstat (limited to 'support/splint/tex/yycommon.sty')
-rw-r--r-- | support/splint/tex/yycommon.sty | 588 |
1 files changed, 588 insertions, 0 deletions
diff --git a/support/splint/tex/yycommon.sty b/support/splint/tex/yycommon.sty new file mode 100644 index 0000000000..5058fafe8a --- /dev/null +++ b/support/splint/tex/yycommon.sty @@ -0,0 +1,588 @@ +% Copyright 2012-2014, 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{\toksa={#1}\expandafter\toksb\expandafter{#2}\edef#2{\noexpand\sts{\the\toksa}\the\toksb}} + +% 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\toksa\expandafter{#2}\edef#2{\noexpand\sts{\the#1}\the\toksa}} + +% 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 + #2\expandafter\expandafter\expandafter{\expandafter\the\expandafter#1\the#2}% +} + +\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}}% +} + +% 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 make 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 argumens 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 below: +% \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 in the strings and 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\yysecondofthree#1#2#3{#2} +\long\def\yythirdofthree#1#2#3{#3} + +% arrays of integers are going to be 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 +% \vara=\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, as 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{% the original meaning of this macro + \ifcase\expandafter#2\the#1\else\fi +} + +\def\getelemof#1\at#2{% no longer limited to registers for #2 + \expandafter\get@lemof\expandafter{\the#1}{#2}% +} + +\def\get@lemof#1#2{% + \ifcase#2 #1\else\fi +} + +\def\fastgetelemof#1\at#2{% + \csname #1\parsernamespace\number#2\endcsname +} + +\def\fgetelemof#1\at#2{% + \expandafter\ifx\csname optopt[#1]\parsernamespace\endcsname\relax + \expandafter\getelemof\csname #1\endcsname\at{#2}% + \else + \csname #1\parsernamespace\number#2\endcsname + \fi +} + +% a nestable loop + +\def\bloop#1\repeat{#1\bloop{#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\derrmessage{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\derrmessage{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\derrmessage{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\default\relax + +\def\grabaction#1#2\grabaction{\toksa{#1}} + +% 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 undefined 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 + +% macros for taking care of extra tokens + +\long\def\yyid#1{#1} +\long\def\yypione#1#2{#1} +\long\def\yypitwo#1#2{#2} +\long\def\yyswap#1#2{#2#1} +\long\def\eatone#1{} +\long\def\eattwo#1#2{} +\long\def\eattoend#1\end{} + +\input xarithm.sty + +% temporaries + +\input trt1.sty + +% \tempcd used by \printrule and implicit rule name macros in yymisc.sty +% \tempce used by implicit rule name macros in yymisc.sty + +% \tokse and \toksf so far only used in the bison action for +% \codepropstype + +\newif\ifbootstrapmode |