diff options
Diffstat (limited to 'support/splint/tex')
24 files changed, 10195 insertions, 0 deletions
diff --git a/support/splint/tex/btokenset.sty b/support/splint/tex/btokenset.sty new file mode 100644 index 0000000000..07affb717e --- /dev/null +++ b/support/splint/tex/btokenset.sty @@ -0,0 +1,31 @@ +% 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/>. + +\prettywordpair{\%<flag>}{{$\langle\star\rangle$}} +\prettywordpair{\%nondeterministic-parser}{{$\langle$non...ic-parser$\rangle$}} +\prettywordpair{PERCENT_NONDETERMINISTIC_PARSER}{PER...NON...IC\_PARSER} +\prettywordpair{semi}{{\tt;}} +\prettywordpair{TAG}{{{\tt<}{\it tag\/}{\tt>}}} +\prettywordpair{<tag>}{{{\tt<}{\it tag\/}{\tt>}}} +\prettywordpair{FLEX_OPTION}{{$\langle$\bf option$\rangle_{\rm f}$}} +\prettywordpair{FLEX_STATE_X}{{$\langle$\bf state-x$\rangle_{\rm f}$}} +\prettywordpair{FLEX_STATE_S}{{$\langle$\bf state-s$\rangle_{\rm f}$}} +\prettywordpair{ID}{{\cyr\lqq{\rm identifier}\rqq}} +\prettywordpair{ID_COLON}{{\cyr\lqq{\rm identifier: }\rqq}} +\prettywordpair{NUL}{{$\Lambda$}} +\prettywordpair{INT}{{\bf int}} +\prettywordpair{CHAR}{{\bf char}} +\prettywordpair{STRING}{{\cyr\lqq{\tt string}\rqq}} diff --git a/support/splint/tex/dcols.sty b/support/splint/tex/dcols.sty new file mode 100644 index 0000000000..2560495d45 --- /dev/null +++ b/support/splint/tex/dcols.sty @@ -0,0 +1,817 @@ +% Copyright 2004-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/>. + +% multicolumn output: +% the general layout of the page is similar to the following, where +% the number of columns and the location and the number of `footnote' +% columns can be adjusted. + +%%%%%%%%%%% %%%%%%%%%%% %%%%%%%%%%% +%%column1%% %%column2%% %%column3%% +%%%%%%%%%%% ----------- %%%%%%%%%%% +%%%%%%%%%%% %footnotes% %%%%%%%%%%% + +\newskip\realfootins +\newskip\footglue +\newskip\adjskip % skip to improve \vboxes +\newcount\linecount +\newcount\noofcolumns +\newcount\fnotesstart +\newcount\fnotesspan +\newdimen\columnwidth +\newdimen\icgap + +\newdimen\pagewidth +\newdimen\pageheight +\newdimen\longvsize % the height of all the columns combined +\newdimen\fnoteboxwidth +\newdimen\footvboxht % holds the previous value of the height of the + % box of footnotes + +\newbox\partialpage +\newbox\currentcolumn +\newbox\foothbox % holds the footnotes `in one line' +\newbox\foothhbox % holds every footnote in a separate \hbox +\newbox\migrantbox +{\setbox\migrantbox=\box\migrantbox} + +\newtoks\fromword +\newtoks\toword + +\newcount\remaindergaps % the number of gaps between columns after the + % first `footnote column' +\newcount\remaindernonfoots % the number of columns without footnotes + % after the columns with footnotes + +\newif\ifoutputnow +\newif\iflastpageup + +\maxdeadcycles=600 % this should be approximately half the \pageheight in points + % to handle the case when \enddoublecolumns is called before the + % last doublecolumn page is full + +% setup the page length and the column count + +\linecount=53 % number of lines in a page +\fnotesstart=1 % start footnotes under the first column +\fnotesspan=2 % footnotes span two columns +\noofcolumns=2 + +\realfootins=12pt plus 1pt minus 1pt +\footglue=1em plus.2em minus.1em + +\adjskip=0pt plus 6pt +\topskip=9pt + +% + +\def\setmcparams{% + \columnwidth=\hsize + \advance\columnwidth-\noofcolumns\icgap + \advance\columnwidth\icgap + \divide\columnwidth by\noofcolumns +% \advance\linecount\m@ne +% \vsize=\baselineskip +% \multiply\vsize by \linecount +% \advance\vsize by \topskip +% \advance\linecount\@ne + % + \longvsize=\vsize + \advance\longvsize by-\topskip + \advance\longvsize by\baselineskip + \divide\longvsize\baselineskip + \multiply\longvsize\baselineskip + \count\@cclv\noofcolumns + \multiply\longvsize by \count\@cclv + \advance\longvsize-\baselineskip + \advance\longvsize\topskip +} + +\setmcparams +\skip\footins=\realfootins +\count\footins=\@m % 1000 + +\pagewidth=\hsize +\pageheight=\vsize + +% + +\def\footnote#1{% + \edef\@sf{\spacefactor\the\spacefactor}\setfnmark + \@sf + \insert\footins{\floatingpenalty\@MM % 20000 + \setbox\z@=\hbox{\fnfsize\strut\fnmark\localfn\nobreak + \enskip{#1}\penalty-10\hskip\footglue}% + \setfootnoteheight + \box\z@ + }% +} + +\def\setfnoteparams{% + \fnfsize +% \emergencystretch=10pt + \hbadness\@M % 10000 + \hyphenpenalty\z@ \doublehyphendemerits\z@ + \exhyphenpenalty\z@ \finalhyphendemerits\z@ + \righthyphenmin\z@ \lefthyphenmin=\tw@ + \leftskip\z@\rightskip\z@ + \adjdemerits\z@ \uchyph=\@ne \pretolerance=-1 +} + +\let\fnfsize\eightpoint + +\def\setfootnoteheight{ + \global\setbox\foothbox=\hbox{\unhbox\foothbox\unhcopy\z@}% + \setbox\@ne=\vbox{ + \hsize=\fnoteboxwidth + \setfnoteparams + \noindent\unhcopy\foothbox + \par + }% + \dimen\z@=\ht\@ne \advance\dimen\z@ by -\footvboxht + \global\footvboxht=\ht\@ne + \ht\z@=\dimen\z@ \dp\z@=\z@ + \global\setbox\foothhbox=\hbox{\copy\z@\unhbox\foothhbox}} + +\def\makefootnoteparagraph{ + \count\@cclv=\z@ + \unvbox\footins + \makehboxofhboxes + \cleanupfootbuffer\readjustfoots + \setbox\z@=\hbox{\unhbox\z@ \removehboxes} + \setfnoteparams + \noindent\unhbox\z@\par +} + +\def\makehboxofhboxes{% + \setbox\z@=\hbox{}% + \loop + \setbox\tw@=\lastbox + \ifhbox\tw@ + \advance\count\@cclv\@ne + \setbox\z@=\hbox{\box\tw@\unhbox\z@}% + \repeat +} + +% the macro below admittedly stretches \TeX's stack capacity but it is rather efficient +% at removing the \hbox packaging in the correct order. +\def\removehboxes{\setbox\z@=\lastbox + \ifhbox\z@{\removehboxes}\unhbox\z@ \fi} + +\def\cleanupfootbuffer{% remove the footnotes that made it to the page + % form the buffer + \global\setbox\foothhbox=\hbox{\unhbox\foothhbox\cleanupf@otbuffer}} + +\def\cleanupf@otbuffer{% + \ifnum\count\@cclv>\z@ + \setbox\z@=\lastbox + \advance\count\@cclv\m@ne + \let\next=\cleanupf@otbuffer + \else + \let\next=\relax + \fi + \next} + +\def\readjustfoots{% + \setbox\@ne=\copy\foothhbox % keep the footnotes that did not make it + % in the buffer + \setbox3=\vbox{}% + \global\setbox\foothbox=\hbox{}% + \setbox\@ne=\hbox{\unhbox\@ne\readjustf@ots}% +} + +\def\readjustf@ots{% + \setbox\tw@=\lastbox + \ifvoid\tw@ + \let\next=\readjustf@@ts + \else + \global\setbox\foothbox=\hbox{\unhbox\foothbox\unhcopy\tw@}% + \setbox3=\vbox{\box2\unvbox3}% + \let\next=\readjustf@ots + \fi + \next +} + +\def\readjustf@@ts{% + \setbox\tw@=\vbox{ + \hsize=\fnoteboxwidth + \setfnoteparams + \noindent\unhcopy\foothbox\par + } + \global\footvboxht=\ht\tw@ + \dimen\z@=\ht\tw@ \advance\dimen\tw@ by -\ht3 + \ifnum\dimen\z@=\z@ + \else + \global\setbox\footins=\vbox{}% + \advance\dimen\z@ by \m@ne sp + \ht\footins=\dimen\z@ \dp\footins=\@ne sp % to indicate that this is an + % adjustment box for inner (i.e. the ones inserted by \footblock rathar than + % as part of the main output routine) footnotes (looked at by the output routine); + % if the height of the already contributed footnotes needs to be + % adjusted, adjust the height of the \box\footins by that amount + \fi +} + +\fnoteboxwidth=\pagewidth % footnotes will spread across the whole page + +\newskip\dsskip + +\dsskip\smallskipamount + +\def\begindoublecols{\begingroup\r@ggedbottomfalse\parindent=0pt + \count\footins=\@m \multiply\count\footins by\fnotesspan + \skip\footins=\fnotesspan\realfootins + \remaindergaps=\noofcolumns + \advance\remaindergaps by -\fnotesstart + \remaindernonfoots=\remaindergaps + \advance\remaindernonfoots by -\fnotesspan + \advance\remaindernonfoots\@ne + \ifnum\noofcolumns>\@ne % typesetting in one column is an exception, + % otherwise ... + % first, calculate the intercolumn skip ... + \dimen\z@=\pagewidth \dimen\@ne=\columnwidth + \multiply\dimen\@ne by\noofcolumns \advance\dimen\z@ by-\dimen\@ne + \count\@cclv=\noofcolumns \advance\count\@cclv\m@ne + \divide\dimen\z@ by\count\@cclv + \count\@cclv=\fnotesspan + \advance\count\@cclv\m@ne + \dimen\@ne=\columnwidth + \multiply\dimen\@ne by\fnotesspan + \advance\dimen\@ne by \count\@cclv\dimen\z@ + % ... to get the width of the footnote box + \fnoteboxwidth=\dimen\@ne + \fi + % this final modification is needed due to the fact that the whole + % page is put in \hbox to\hsize{...; without the modification the + % width of the footnote box is not going to match the width of the + % page, and when the footnotes span all the columns there will be no + % `\hfill' to compensate for arithmetic imprecision + \ifnum\fnotesspan=\noofcolumns + \fnoteboxwidth=\pagewidth + \fi + % + \output={ + \ifvoid\partialpage + \else % this is a border case: too much material has been contributed, this routine will be called twice + % so output the full page now + \normaloutput{\unvbox\partialpage}\lheader\rheader + \fi + \global\setbox\partialpage=\vbox{\unvbox\@cclv\vskip\dsskip}% + \dimen\z@=\longvsize + \advance\dimen\z@ by -\noofcolumns\ht\partialpage + \ifnum\dimen\z@<\z@ % the amount of material contributed to the current page is more than the + % required \vsize (so that \pageshrink would have to be involved); + % output the page normally + \normaloutput{\unvbox\partialpage}\lheader\rheader + \else % move the footnotes into the buffer, recalculate their size + \migratefootnotes + \fi + }% + \eject + \def\footnoterule{\kern -3\p@ \hrule width \fnoteboxwidth \kern 2.6\p@}% + \outputnowfalse % not ready for immediate output, play with dimensions first + \lastpageupfalse % not the final page yet + \holdinginserts=\@ne + \let\thepage\pagesofar + \output={\multcolumnout} + \hsize=\columnwidth + \global\vsize=\pageheight% + \global\advance\vsize by-\ht\partialpage% + \global\divide\vsize\baselineskip + \global\multiply\vsize\baselineskip + \global\multiply\vsize\noofcolumns% +%\message{starting with vsize at \the\vsize, with pp at \the\ht\partialpage} + \global\advance\vsize by-\noofcolumns\topskip + \global\advance\vsize by\topskip + \global\advance\vsize by\noofcolumns\baselineskip + \global\advance\vsize by-\baselineskip +%\message{vsize set at \the\vsize} + \ifvoid\migrantbox + \else + \insert\footins{\box\migrantbox}% + \fi +} + +\newif\ifpenultimatepage +\newif\ifp@nultimatepage + +\def\enddoublecols{\par % fire the page buidling routine + \ifnum\pagetotal>\pagegoal + \global\penultimatepagetrue + \eject % if the multicolumn output ended just barely after accumulating a full page + \fi % but before the page is shipped out, output the page with the standard multicolumn output + \dimen7 =\pagegoal + \vsize=\longvsize + % now recalculate all the dimensions assuming that the footnotes stretch across the whole page + \ifnum\footvboxht>\z@ + \advance\vsize by \fnotesspan\footvboxht + \advance\dimen7 by \fnotesspan\footvboxht + \advance\vsize by -\noofcolumns\realfootins + \advance\vsize by \fnotesspan\realfootins + \advance\dimen7 by -\noofcolumns\realfootins + \advance\dimen7 by \fnotesspan\realfootins + \fi + \fnotesspan=\noofcolumns + \fnotesstart=\@ne + \remaindergaps=\noofcolumns + \advance\remaindergaps by -\fnotesstart + \remaindernonfoots=\z@ + \fnoteboxwidth=\pagewidth + \setbox\z@=\hbox{}\setfootnoteheight + % calculate and adjust the height of the footnotes; this introduces an extra \hbox to \foothhbox + % remember this when in the output routine for the last page! + \advance\vsize by -\noofcolumns\footvboxht + \advance\dimen7 by -\noofcolumns\footvboxht + \pagegoal=\dimen7 + % + \lastpageuptrue + \ifp@nultimatepage % everything has been output already + \global\penultimatepagefalse + \global\p@nultimatepagefalse + \else + \global\penultimatepagefalse + \eject + \fi + \endgroup + \holdinginserts=\z@ + \global\pagegoal=\pageheight + \global\vsize=\pageheight} + +\def\migratefootnotes{% + \ifvoid\footins + \else + \ifdim\dp\footins=\z@ % it is not a correction + \setbox\@ne=\vbox{\unvbox\footins + % similar to \makehboxofhboxes + \setbox\z@=\hbox{}% + \loop + \setbox\tw@=\lastbox + \ifhbox\tw@ + \setbox\z@=\hbox{\unhbox\tw@\unhbox\z@}% + \repeat + % ... + \setbox\foothbox=\hbox{}% + \setbox\foothhbox=\hbox{}% + \footvboxht=\z@ + \setfootnoteheight\global\setbox\migrantbox=\box\z@ + } + \else + {\global\setbox\footins=\box\footins}% + \fi + \fi +} + +\def\multcolumnout{% + \splittopskip=\topskip + \splitmaxdepth=\maxdepth + \dimen\z@=\pageheight + \advance\dimen\z@ by-\ht\partialpage + \advance\dimen\z@ by-\dp\partialpage + \ifnum\dimen\z@<\baselineskip % another extreme case: at most one line will fit, so + % the adjustments to \vsize will not change the page layout + % quickly enough resulting in an infinite \deadcycles loop + \normaloutput{\unvbox\partialpage}\lheader\rheader + \unvbox\@cclv \penalty\lastpenalty + \fi + \divide\dimen\z@\baselineskip \multiply\dimen\z@\baselineskip +%\message{aiming for d0: \the\dimen0} + \dimen\@ne=\pagegoal % we claculate the maximum allowable height of the + % middle column next + \advance\dimen\@ne by-\vsize + \advance\dimen\@ne by \fnotesspan\dimen\z@ + \divide\dimen\@ne by\fnotesspan +%\message{d1: \the\dimen1, d0: \the\dimen0, pageheight: \the\pageheight }% +%\message{(vsize: \the\vsize, pagegoal: \the\pagegoal\space ppage: \the\ht\partialpage)^^J^^J}% + % + \balanceallcolumns + % + \ifoutputnow + \global\fromword=\expandafter{\firstmark} + \global\toword=\expandafter{\botmark} + \iflastpageup + \ifnum\outputpenalty<-9999 % this break was forced (most likely by the \break in \enddouble...) + \ifvoid\footins + \else + \ifdim\dp\footins=\z@ \else + {\setbox\footins=\box\footins}% this was a correcion box after which no new real footnotes + \fi % were cotributed + \fi + % a correction (\hbox{}) was added by the \enddouble... command; + % this correction will affect \box\footins (since it will appear + % as a box in \foothhbox, a box that is not a footnote); + % this correction will be translated into an appropriate + % adjustment to \box\footins (since the output routine thinks + % it is a footnote); however, it does throw off the footnote count in \foothhbox + % off by one; kill it here; the footnotes will be inserted from the footins box + \setbox\z@=\vbox{\pagesofar}% + \unvbox\z@ \penalty\lastpenalty + % since we could not touch \foothhbox above (to keep the footnote height calculations correct), + % the \footins box is messed up; fix it + {\setbox\footins=\box\footins}% + \global\setbox\foothhbox=\hbox{}% to keep the footnote counting + \global\setbox\foothbox=\hbox{}% consistent + \global\footvboxht=\z@ + \else + \normaloutput\page\lheader\rheader + % + \global\vsize=\longvsize + \global\outputnowfalse + \global\holdinginserts=\@ne + \fi + \else % this is not the last page, preform normal multicolumn output + \normaloutput\page\lheader\rheader + % + \global\vsize=\longvsize + \global\outputnowfalse + \global\holdinginserts=\@ne + \ifpenultimatepage % page broken at a penalty inserted by \enddoublecolumns + \global\p@nultimatepagetrue % the next penalty should be removed + \fi + \fi + {\setbox\@cclv=\box\@cclv}% use up \box255 ! + \else % do not output yet, see if adjustments worked + \ifnum\dimen\tw@>\dimen\@ne + \global\advance\vsize by -\fnotesspan pt + \else + \global\outputnowtrue + \global\holdinginserts=\z@ + \fi + \unvbox\@cclv + \ifnum\outputpenalty=\@M % 10000 the break was not at a penalty item + \else + \ifp@nultimatepage % we already split the page at this penalty + \global\p@nultimatepagefalse % let \enddoublecolumns insert the penalty + \else + \penalty\outputpenalty + \fi + \fi + \fi +} + +% we will change some of the plain TeX macros used by cwebmac + +\def\pagebody{% + \vbox to \pageheight{ + \boxmaxdepth=\maxdepth \pagecontents + \the\footline + \ifr@ggedbottom + \vskip\adjskip + \fi + } +} + +\def\normaloutput#1#2#3{\ifodd\pageno\hoffset=\pageshift\fi + \shipout\vbox{ + \vbox to\fullpageheight{ + \iftitle\global\titlefalse + \else\hbox to\pagewidth{\vbox to10pt{}\ifodd\pageno #3\else#2\fi}\fi + \vfill#1}} % parameter #1 is the page itself + \global\advance\pageno by1} + +\let\page\pagebody % this is a cwebmac command but it has to be executed here, after the \pagebody macro is changed + +\def\pagecontents{ + \ifvoid\topins + \else + \unvbox\topins + \fi + \setbox\z@=\vbox{\thepage}\dimen\z@=\dp\z@ % for \ruggedbottom + \unvbox\z@ + \ifr@ggedbottom + \kern-\dimen\z@\vfil + \fi + \ifvoid\footins + \else + \ifnum\dp\footins=\z@ % this is not an adjustment + \vskip\realfootins\footnoterule + \vbox{\hsize=\pagewidth\makefootnoteparagraph}% + \fi + \fi +} + +\def\thepage{\unvbox\@cclv} + +\def\balanceallcolumns{ + \tcthr=\vbadness + \vbadness=1000000 % set \vbadness to the badness of a overfull box + \count\@cclv\z@ % (does not really prevent TeX from reporting one) + \setbox\z@=\vbox{\unvcopy\@cclv}% + \setbox\tw@=\vbox{}%%% this box is changed globally + \b@lanceallcolumns +} + +\def\b@lanceallcolumns{ + \advance\count\@cclv\@ne + \whichcolumn{\count\@cclv}% + \ifinfoots % if the footnotes go under these columns ... + \dimen\tw@=\ht\z@ +%\message{set d2(=ht0): \the\dimen2, d0: \the\dimen0; vs. ph: \the\pageheight}% + \advance\dimen\tw@ by -\remaindernonfoots\dimen\z@ + \advance\dimen\tw@ by -\remaindergaps\baselineskip + \advance\dimen\tw@ by \remaindergaps\topskip + \divide\dimen\tw@ by \fnotesspan +%\message{set d2: \the\dimen2}% + \let\next=\b@l@nceallcolumns + \else % otherwise, split off the columns ... + \ifnum\dimen\z@<\topskip + \setbox\@ne=\vsplit\z@ to \topskip + \else + \setbox\@ne=\vsplit\z@ to \dimen\z@ + % see a remark below on why this was necessary + \fi + \wd\@ne=\hsize + \setbox\tw@=\vbox{\box\@ne \unvbox\tw@}%%% this box is changed globally + \let\next=\b@lanceallcolumns + \fi + \next +} + +\newcount\tcthr + +\def\b@l@nceallcolumns{% splitting off the columns after the footnotes start + \count\@cclv=\fnotesstart + \setbox3=\copy\z@ + \setbox5=\vbox{}% + \b@l@nc@allcolumns +} + +\def\b@l@nc@allcolumns{ + \whichcolumn{\count\@cclv}% + \iflastcolumn +%\message{box3 height: \the\ht3, box3 depth: \the\dp3, d0: \the\dimen0, d2: \the\dimen2}% + \ifnum\ht3>\dimen\ifinfoots \tw@ \else \z@ \fi + \advance\dimen\tw@ by \@ne pt + \let\next=\b@l@nceallcolumns + \else + \ifinfoots + \else + \ifnum\dimen\z@<\topskip + \setbox3=\vsplit3 to \topskip + \else + \setbox3=\vsplit3 to \dimen\z@ + \fi + \fi +%\message{**box3 height: \the\ht3, d0: \the\dimen0, bs: \the\baselineskip, ts: \the\topskip}% + \wd3=\hsize + \setbox\tw@=\vbox{\box3 \unvbox5 \unvbox\tw@}% + %%% \box2 is laterchanged globally + \vbadness=\tcthr + \let\next=\relax + \fi + \else + \ifnum\dimen\ifinfoots \tw@ \else \z@ \fi<\topskip + \setbox4=\vsplit3 to \topskip + \else + \setbox4=\vsplit3 to \dimen\ifinfoots \tw@ \else \z@ \fi + \fi + % the code above is a replacement for: + % \setbox4=\vsplit3 to \dimen\ifinfoots \tw@ \else \z@ \fi + % \ifnum\badness>\@MM \errmessage{\the\badness:\the\vbadness}\fi + % the replacement was necessary to avoid `Overfull \vbox ... ' warnings + % that (unlike those for underfull boxes) cannot be silenced by raising + % \vbadness + \wd4=\hsize + \setbox5=\vbox{\box4 \unvbox5}% + \advance\count\@cclv\@ne + \let\next=\b@l@nc@allcolumns + \fi + \next +} + +\def\pagesofar{% + \unvbox\partialpage + \count\@cclv\z@ + \hbox to\pagewidth{\p@gesofar}% + \kern-\prevdepth + \vskip\adjskip +} + +\def\p@gesofar{\advance\count\@cclv\@ne + \whichcolumn{\count\@cclv}% + \ifinfoots + \let\next=\footblock + \else + \iflastcolumn + \getnextcolumn\box\currentcolumn + \let\next=\relax + \else + \getnextcolumn\box\currentcolumn\hfil + \let\next=\p@gesofar + \fi + \fi + \next +} + +\def\footblock{% + \hbox to \fnoteboxwidth{\f@otblock}% + \count\@cclv=\fnotesstart + \advance\count\@cclv by\fnotesspan + \advance\count\@cclv\m@ne + \whichcolumn{\count\@cclv}% + \iflastcolumn + \let\next=\relax + \else + \hfil + \let\next=\p@gesofar + \fi + \next +} + +\def\f@otblock{% + \whichcolumn{\count\@cclv}% + \ifinfoots + \iffirstfootcol + \setbox\z@=\rlap{\vbox{ + \ifvoid\footins + \else + \ifdim\dp\footins=\z@ + % footnote info is present + \vskip\realfootins\footnoterule + \vbox{\hsize=\fnoteboxwidth\makefootnoteparagraph} + \fi + \fi + }}% + \dimen5=\ht\z@ + \dimen6=\dimen5 + \advance\dimen6 by\dimen\tw@ + \setbox\z@=\vbox{ + \getnextcolumn\unvbox\currentcolumn\kern-\dimen3 + \vskip\adjskip + \box\z@ + }% + \ifnum\ht\z@>\baselineskip + \setbox\z@=\vbox to \dimen\iflastpageup 6 \else \z@ \fi{\unvbox\z@}% + \fi + \wd\z@=\hsize + \box\z@ + \else + \hfil\setbox\z@=\vbox{ + \getnextcolumn\unvbox\currentcolumn\kern-\dimen3 + \vskip\adjskip + \hrule width\z@ height \dimen5 depth\z@ + }% + \ifnum\ht\z@>\baselineskip + \setbox\z@=\vbox to \dimen\iflastpageup 6 \else \z@ \fi{\unvbox\z@}% + \fi + \wd\z@=\hsize + \box\z@ + \fi + \iflastcolumn + \let\next=\relax + \else + \let\next=\f@otblock + \fi + \else + \let\next=\relax + \fi + \advance\count\@cclv\@ne + \next +} + +\def\getnextcolumn{% + \global\setbox\tw@=\vbox{\unvcopy\tw@ \global\setbox\currentcolumn=\lastbox}% + \dimen3=\dp\currentcolumn +} + +\newif\ifinfoots +\newif\iflastcolumn +\newif\ifbeforefoots +\newif\iffirstfootcol + +\def\whichcolumn#1{% + \infootsfalse + \lastcolumnfalse + \beforefootsfalse + \firstfootcolfalse + \ifnum#1<\fnotesstart + \beforefootstrue + \else + \ifnum#1=\fnotesstart + \firstfootcoltrue + \infootstrue + \else + \advance\fnotesstart by\fnotesspan + \ifnum#1<\fnotesstart + \infootstrue + \fi + \advance\fnotesstart by-\fnotesspan + \fi + \ifnum#1=\noofcolumns + \lastcolumntrue + \fi + \fi +} + +% footnote counting macros + +\let\footthenotes\empty +\footline{\footthenotes}% so the footnotes know where to reset + +\def\fnmark#1{{% + \ifnum#1<\@M + \setbox\z@=\hbox{\rm)}\vbox to \ht\z@{\hbox{$\scriptstyle\the#1$}\vss}\box\z@ + \else + \setbox\z@=\hbox{\rm)}\setbox2=\hbox{$\scriptstyle0$}% + \setbox\@ne=\hbox{\vrule width\wd2 height\ht2}% + \vbox to \ht\z@{\box\@ne\vss}\box\z@ + \fi}} + +\def\addfnlabel{\expandafter\fnstream\expandafter{\the\fnstream*}} +\def\addpgendlabel{\expandafter\fnstream\expandafter{\the\fnstream|}} + +% the commands above will be exectuted when the .ftn file is loaded below + +\newtoks\fnstream % locations of footnotes +\fnstream={} + +% before processing the footnotes one by one we have to open an +% auxiliary file (we have to read it in whole because it will be +% rewritten as the document is being typeset); this opening has to be +% done carefully for the file might not be there yet; check for it first. + +\newread\fnlabels +\newwrite\fnlabels +\newcount\localfn % footnote count +\newcount\fniteration + +\def\setupfootnotes{% this macro should be used at the beginning of the file, after a box (preferably) + \def\footthenotes{\write\fnlabels{\noexpand\addpgendlabel}}% + \openin\fnlabels=\jobname.ftn\relax + \ifeof\fnlabels + \closein\fnlabels\relax + \fniteration\z@ + \else + \closein\fnlabels\relax + \input \jobname.ftn\relax + \fi + \edef\savedfnstream{\the\fnstream}% + % now we open the same file for writing ... + \openout\fnlabels=\jobname.ftn\relax + \advance\fniteration\@ne + \write\fnlabels{\noexpand\fniteration\the\fniteration\space}% +} + +\def\unsetfootnotes{% a clean(er) way to terminate footnote accounting +% \let\footthenotes\footthenoteslast + \def\footthenotes{\closeout\fnlabels\let\footthenotes\empty}% +} + +% the control sequence below is not used, although the idea is clear; +% unfortunately, this does not work, since \closeout\fnlabels is delayed +% so \input \jobname.ftn is likely to import an empty file; +% a more elaborate strategy is possible whereby all the macros inside +% \jobname.ftn are made expandable and the test below (along with \input \jobname.ftn) +% is put inside \write\m@ne{ ... } (so that the expansion of \input \jobname.ftn is +% delayed) using string comparison macros defined elsewhere +% but at the moment it seems excessive + +\def\footthenoteslast{% unused, see above + \closeout\fnlabels + \fnstream{}% + \input \jobname.ftn + \edef\next{\the\fnstream}% + \ifx\next\savedfnstream + \else + \message{Footnotes may be set incorrectly ...}% + \fi + \let\footthenotes\relax +} + +\def\setfnmark{{% + \ifnum\localfn<\@M + \getfntok + \if*\nexttok + \global\advance\localfn\@ne + \else + \global\localfn=\@M + \fi + \fi + \removewhitespace\kern2pt\fnmark\localfn + \write\fnlabels{\noexpand\addfnlabel}% +}} + +\def\getfntok{\loop\splitfnstream\if|\nexttok\global\localfn=\z@ \repeat} + +\def\splitfnstream{\edef\tempdefone{\the\fnstream}% + \ifx\tempdefone\empty + \def\nexttok{?}\message{You need to recount the footnotes ...}% + \else + \expandafter\splitfnstre@m\tempdefone\end + \fi +} + +\def\splitfnstre@m#1#2\end{\def\nexttok{#1}\global\fnstream={#2}} + diff --git a/support/splint/tex/flex.sty b/support/splint/tex/flex.sty new file mode 100644 index 0000000000..da3aa7b0b7 --- /dev/null +++ b/support/splint/tex/flex.sty @@ -0,0 +1,547 @@ +% 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/>. + +\newtoks\tayybyte % throwaway token register +\newcount\tayymarker % throwaway count register + +\chardef\EOL=`\^^J% + +\def\yylex{% + \ifnum\yyg@yyinit=\z@ % if ( !yyg->yy_init ) { + \yyg@yyinit=\@ne % yyg->yy_init = 1; + \ifnum\yyg@yystart=\z@ % if ( ! yyg->yy_start ) { + \yyg@yystart=\@ne % yyg->yy_start = 1; + \fi % } + \fi % } + \yylwhile +} + +\def\yylwhile{% + % yy_cp = yyg->yy_c_buf_p; + % *yy_cp = yyg->yy_hold_char; + % yy_bp = yy_cp; + % + \yycurrentstate=\yyg@yystart % yy_current_state = yyg->yy_start; + \advance\yycurrentstate\YYATBOL % yy_current_state += YY_AT_BOL(); + \yymatch +} + +\newif\ifyytextbackup +\newif\iftraceflexbuffers + +\def\yymatch{% + \ifyytextbackup + \xskiptofi\yyreinput + \else + \xskiptofi\yyinput + \fi +} + +\def\yyreinput{\expandafter\yyresetstreams\expandafter\yyinput\the\yytextseen} + +\def\yyresetstreams{% + \iftraceflexbuffers\ferrmessage{will rescan: \the\yytextseen}\fi + \yytextseen{}% + \yytextseenpure\yytextseen + \yyformatseen\yytextseen + \yystashseen\yytextseen + \yytextbackupfalse +} + +\def\yym@tch{% do { + \yyc=\fgetelemof{yyec}\at\yycp@\relax % yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + \yyact=\fgetelemof{yyaccept}\at\yycurrentstate\relax + % ... ... reuse \yyact ( yy_act = yy_accept[yy_current_state] ) + \ifnum\yyact=\z@ % if ( yy_accept[yy_current_state] ) { + \else % + \yyg@yylastacceptingstate=\yycurrentstate % yyg->yy_last_accepting_state = yy_current_state; + \concat\yytext\yytextseen % yyg->yy_last_accepting_cpos = yy_cp; + \concat\yytextpure\yytextseenpure % ... ... + \concat\yyformat\yyformatseen % ... ... + \concat\yystash\yystashseen % ... ... + \yytextlastchar=\yytextseenlastchar % + \yyfmark=\yyfmarklast % ... ... + \yysmark=\yysmarklast % ... ... + \yytextseen={}% + \yytextseenpure\yytextseen + \yyformatseen\yytextseen + \yystashseen\yytextseen + \fi % } + \yyllwhile +} + +\def\yyllwhile{% ... yyllwhile: + \yyact=\fgetelemof{yybase}\at\yycurrentstate\relax % ... ... reusing \yyact ( yy_act = yy_base[yy_current_state] ) + \advance\yyact\yyc % ... ... ( yy_act = yy_act + yy_c ) + \yyact=\fgetelemof{yychk}\at\yyact\relax % ... ... ( yy_act = yy_chk[yy_act] ( == yy_chk[yy_base[yy_current_state] + yy_c] ) ) + \ifnum\yyact=\yycurrentstate % while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { + \yybreak\yymatchtail % ... if ( yy_chk[yy_base[yy_current_state] + yy_c] == yy_current_state ) + \else % ... goto yy_match_tail; + % ... else + \yycurrentstate=\fgetelemof{yydef}\at\yycurrentstate\relax + % yy_current_state = (int) yy_def[yy_current_state]; + \ifnum\yycurrentstate>\YYMAXREALCHAR\relax % if ( yy_current_state >= sizeof( yy_accept ) ) { + \yyc=\fgetelemof{yymeta}\at\yyc\relax % yy_c = yy_meta[(unsigned int) yy_c]; + \fi % } + \yybreak\yyllwhile % ... goto yyllwhile; + \yycontinue % } +} + +\def\yymatchtail{% + \yycurrentstate=\fgetelemof{yybase}\at\yycurrentstate\relax + \advance\yycurrentstate\yyc % + \yycurrentstate=\fgetelemof{yynxt}\at\yycurrentstate\relax + % yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + \concat\yytextseen\yybyte % ++yy_cp; + \concat\yytextseenpure\yybytepure % ... + \concat\yyformatseen\yyfbyte\yyfbyte{}% % ... + \concat\yystashseen\yysbyte\yysbyte{}% % ... + \yytextseenlastchar=\yycp@ % + \yyfmarklast=\formatmarker % ... + \yysmarklast=\stashmarker % ... + \yyact=\fgetelemof{yybase}\at\yycurrentstate\relax % ... reusing \yyact ( yy_act = yy_base[yy_current_state] ) + \ifnum\yyact=\YYBASEMAXENTRY\relax % } while ( yy_base[yy_current_state] != max( yy_base ) ); + \xskiptofi\yyfindaction % ... if ( yy_base[yy_current_state] == max( yy_base ) ) goto yy_find_action; + \else % ... else goto yy_match; + \xskiptofi\yymatch + \fi +} + +\newif\ifyyflexdebug +\newif\iftracebadchars + +\def\yyfindaction{% + \yyact=\fgetelemof{yyaccept}\at\yycurrentstate\relax % yy_act = yy_accept[yy_current_state]; + \ifnum\yyact=\z@ % if ( yy_act == 0 ) { + \yytextbackuptrue % yy_cp = yyg->yy_last_accepting_cpos; + \yycurrentstate=\yyg@yylastacceptingstate % yy_current_state = yyg->yy_last_accepting_state; + \yyact=\fgetelemof{yyaccept}\at\yycurrentstate\relax% yy_act = yy_accept[yy_current_state]; + \ifyyflexdebug\ferrmessage{backup: \the\yytext:\the\yytextseen}\fi + \else + % + \concat\yytext\yytextseen + \concat\yytextpure\yytextseenpure + \concat\yyformat\yyformatseen + \concat\yystash\yystashseen + \yytextlastchar=\yytextseenlastchar + \yyfmark=\yyfmarklast + \yysmark=\yysmarklast + \yytextseen{}% + \yytextseenpure{}% + \yyformatseen{}% + \yystashseen{}% + % + \fi % } +% \YYDOBEFOREACTION % YY_DO_BEFORE_ACTION; + \ifyyflexdebug + \ferrmessage{action: \the\yyact, state: \the\yycurrentstate\space(\the\yytext)}% + \fi + \doaction +} + +\def\YYRULESETUP{% %#define YY_RULE_SETUP \ + \yytoksempty{\yytext}{}{% % if ( yyleng > 0 ) \ + \ifnum\EOL=\yytextlastchar % YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (yytext[yyleng - 1] == '\n'); \ + \YYATBOL=\@ne % YY_USER_ACTION + \else %#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + \YYATBOL=\z@ + \fi + }% +} + +%#define BEGIN yyg->yy_start = 1 + 2 * +% should be: +%#define BEGIN(state) yyg->yy_start = 1 + 2 * ( state ) + +\newif\iftracestates + +\def\yylexstate#1{\csname flexstate\parsernamespace #1\endcsname} + +\def\yyBEGIN#1{% + \yyg@yystart + \expandafter\ifx\csname flexstate\parsernamespace #1\endcsname\relax + #1 \iftracestates\ferrmessage{now in state: #1}\fi + \else + \csname flexstate\parsernamespace #1\endcsname\relax + \iftracestates\ferrmessage{now in state: #1 (\number\csname flexstate\parsernamespace #1\endcsname)}\fi + \fi + \multiply\yyg@yystart\tw@ + \advance\yyg@yystart\@ne +} + +\def\yyBEGINr#1{% + \yyg@yystart#1% + \iftracestates\ferrmessage{new state: \the\yyg@yystart}\fi + \multiply\yyg@yystart\tw@ + \advance\yyg@yystart\@ne +} + +%#define YY_START ((yyg->yy_start - 1) / 2) + +\def\YYSTART{% + \expandafter\xdivbytwo\expandafter{\number + \expandafter\xdecrement\expandafter{\number\yyg@yystart}} +} + +\def\yypushstate#1{% + \expandafter\yypush\expandafter{\number\YYSTART}\on\yystatestack + \yyBEGIN{#1}% +} + +\def\yypopstate{% + \yypop\yystatestack\into{\expandafter\yyBEGIN\romannumeral0}% + \iftracestates\message{new state (* 2 + 1 scrambled): \the\yyg@yystart}\fi +} + +\def\yytopstate#1{% + \yyreadstack\yystatestack\at\z@\to#1% +} + +\let\yylexcontinue\yylwhile % complete the while loop (requires \yylexnext) +\def\yylexcontinue{\yytext{}\yytextpure\yytext\yylwhile} % complete the while loop + +% \yylextail is the return point from the lexer + +\let\yyreturn\yym@tch % the return point from the low-level input + +\def\yylexreturnbootstrap#1{% + \yytext{}\yytextpure\yytext + \expandafter\ifx\csname token\parsernamespace #1\endcsname\relax + % this token value is undefined + \let\yylextail\yylex % so lex the next token + \else + \yychar\csname token\parsernamespace #1\endcsname\relax + \let\yylextail\yyparsetail + \fi +} + +\def\yylexreturnregular#1{\yychar\csname token\parsernamespace #1\endcsname\relax\yytext{}\yytextpure{}\let\yylextail\yyparsetail} + +\def\yylexreturnval#1{% return value (yytext) only + \yychar\csname token\parsernamespace #1\endcsname\relax + \yylval\expandafter{\expandafter{\the\yytext}}% + \yylval\expandafter\expandafter\expandafter{\expandafter\the\expandafter\yylval\expandafter{\the\yytextpure}}% + % the above is an equivalent of + % \edef\next{\yylval{{\the\yytext}{\the\yytextpure}}}\next + % but does not `pollute' the definition of \next + \yytext{}\yytextpure\yytext\let\yylextail\yyparsetail +} + +\def\yylexreturnptr#1{% return stream pointers only + \yylval\expandafter{\expandafter{\the\yyfmark}}% + \yylval\expandafter\expandafter\expandafter{\expandafter\the\expandafter\yylval\expandafter{\the\yysmark}}% + % the above is an equivalent of + % \edef\next{\yylval{{\the\yyfmark}{\the\yysmark}}}\next + % but does not `pollute' the definition of \next + \yylexreturn{#1}% +} + +\def\yylexreturntext{\yylexreturnptr{\the\yytextpure}} + +\def\yylexreturnraw#1{% return the character value + \yychar`#1\relax + \yytext{}\yytextpure{}\let\yylextail\yyparsetail +} + +\def\yylexreturnchar{% + \expandafter\yylexreturnraw\the\yytextpure +} + +\def\yylexnext{\yytext{}\yytextpure{}} % use this with a trivial \yylexcontinue +\let\yylexnext\empty + +\def\yyterminate{\yychar\YYEOF\yylval{}\yytext{}\yytextpure{}\let\yylextail\yyparsetail} + +\def\yyerrterminate{\yylexreturn{$undefined}} %$ + +\def\ferrmessage#1{\immediate\write16{#1}} + +% \yyless is slow and the macros below have not been tested in their current +% form: avoid them + +\def\yyless#1{% + \ifnum#1=\z@ + \ROLLBACKCURRENTTOKEN + \else + \let\oldyyreturn\yyreturn + \edef\yyreturn{\noexpand\yyskipnchars{\number#1}}% + \expandafter\yyinput\the\yytext\yyeof + \fi +} + +\def\yyskipnchars#1{% + \ifnum\yycp@=\YYENDOFBUFFERCHAR % read \yyeof + \yycomplain{yyless buffer overflow: #1 characters too many}% + \else + \ifnum#1=\@ne % skipped the required number of tokens + \yybreak@\yyl@ss + \else + \edef\yyreturn{\noexpand\yyskipnchars{\xdecrement{#1}}}% + \yybreak@\yyinput + \fi + \yycontinue +} + +\def\yyl@ss#1\yyeof{% + \yytext{#1}% + \concatl\yytext\yytextseen + \yytext{}\yytextpure{}% + \yytextbackuptrue + \let\yyreturn\oldyyreturn +} + +%#define ROLLBACK_CURRENT_TOKEN \ +% do { \ +% scanner_cursor.column -= mbsnwidth (yytext, yyleng, 0); \ +% yyless (0); \ +% } while (0) + +\def\ROLLBACKCURRENTTOKEN{% + \concatl\yytext\yytextseen + \yytext{}\yytextpure{}% + \yytextbackuptrue +} + +% \yytext---current yytext +% \yytextseen---last accepted yytext +% |--\yytext--|--\yytextseen--|--remaining buffer--| +% after accepting state: +% [---------\yytext-----------] +% after backing up: +% |--\yytext--|--\yytextseen-----remaining buffer--| +% \yytextseen={} + +%#define YY_DO_BEFORE_ACTION \ +% yyg->yytext_ptr = yy_bp; \ +% yyleng = (size_t) (yy_cp - yy_bp); \ +% yyg->yy_hold_char = *yy_cp; \ +% *yy_cp = '\0'; \ +% yyg->yy_c_buf_p = yy_cp; + +\def\doaction{% + \yydoactionswitch\yyact +} + +%#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +% as the macros above and below make a lot of assignments, +% expandability was not a +% priority, however, keeping the macro namespace clean was; +% expandability is, of course a guaranteed way to do so, grouping is +% another; + +\def\yylexeofaction{% + \yygetnextbuffer + \ifYYEOBLASTMATCH + \yygetpreviousstate + \ifyyflexdebug\ferrmessage{found previous state: \the\yycurrentstatelocal\space matched text: \the\yytext>>\the\yytextseen(\the\yybyte))}\fi + \yycurrentstate\yycurrentstatelocal + \let\yylextail\yyfind@ction + \YYEOBLASTMATCHfalse + \else + \yyact\YYENDOFBUFFER\relax + \advance\yyact\YYSTART + \advance\yyact\@ne % yy_act = YY_STATE_EOF(YY_START); + \let\yylextail\doaction % goto do_action; + \appendl\yytextseen{\the\yytext}\yytextbackuptrue % in case the scanner gets called again + \ifyyflexdebug + \yytoksempty{\yytext}% + {\errmessage{internal error: matched nothing in eob state}}% + {\yyisthiscsr\yytext\yyeof{}{\errmessage{internal error: matched more that a single eob}}}% + \ferrmessage{eob in user state: \the\yyact\space matched text: \the\yytext(\the\yytextpure)\space + to read: \the\yytextseen}% + \fi + \yytext{}% + \fi +} + +\def\yygetnextbuffer{% + \yytoksempty{\yytext}{\errmessage{internal error: empty matched text in eob state}}% + {% + \expandafter\expandafter\expandafter + \yystringempty % we have matched exactly one token + \expandafter\expandafter\expandafter{\expandafter\eatone\the\yytext}% + {\YYEOBLASTMATCHfalse}{\YYEOBLASTMATCHtrue}% + }% +} + +\def\yyeofcontainer{\yyeof} + +\newif\ifYYEOBLASTMATCH + +\def\yygetpreviousstate{% + \yycurrentstatelocal=\yyg@yystart + \advance\yycurrentstatelocal\YYATBOL + % + \yytoksempty{\yytext}{\errmessage{internal error: empty matched text in eob state}}{}% + \expandafter\yysplitoff\expandafter.\the\yytext\yyeof\end + \appendl\yytextseen{\noexpand\yyeof}\yytextbackuptrue + \ifyyflexdebug\ferrmessage{searching for last match in text: \the\yytext}\fi % TODO: delete + \yytoksempty{\yytext}{}{% yyg->yytext_ptr >= yyg->yy_c_buf_p /* do not enter the for loop */ + \yytextpure{}% + \yyfutureyytext\yytextseen % to be reinserted in yyfind@action + \yytextseen{}\yytextseenpure{}% + \expandafter\yytext\expandafter + {\expandafter}\expandafter + \yygetpreviousstatefor\the\yytext\splitoffend % at least one iteration of the for loop + }% +} + +\def\yysplitoff#1\yyeof#2\end{% + \yystringempty{#2}{% + \errmessage{internal error: something other than \noexpand\yyeof\space triggered eob action}% + }{% + \yytext\expandafter{\eatone#1}% to remove the `.' at the beginning + }% +} + +\def\yygetpreviousstatefor{% + % save all the lexer variables affected by \yyinput + % to be restored on exit from the `for' loop + % i.e.~when the \splitoff token is read + \let\currentyyreturn\yyreturn +% + \let\currentyyfbyte\yyfbyte + \let\currentyysbyte\yysbyte + \let\currentstashmarker\stashmarker + \let\currentformatmarker\formatmarker +% + \let\yyfbyte\tayybyte + \let\yysbyte\tayybyte + \let\stashmarker\tayymarker + \let\formatmarker\tayymarker +% + \let\yyreturn\yygetpreviousstatef@r + \yyinput +} + +\def\yygetpreviousstatef@r{% + \let\default\yygetpreviousstatedefault + \ifyyflexdebug\ferrmessage{just read: \the\yybyte}\fi % TODO: delete + \switchon{\expandafter\getfirsttoken\expandafter{\the\yybyte}}\in\yygetpreviousstateswitch +} + +\def\yygetpreviousstateswitch{% + \yyeof {% scanned a NUL + \yyclocal\YYECMAGIC\relax % the constant extracted from yy_get_next_state + \yygetpreviousstat@f@r + } + \splitoffend {% yyg->yytext_ptr >= yyg->yy_c_buf_p /* exit the for loop */ + % this is not an actual character but a marker for the end of the `for' loop + \let\yyfbyte\currentyyfbyte + \let\yysbyte\currentyysbyte + \let\stashmarker\currentstashmarker + \let\formatmarker\currentformatmarker + \yycp@=\YYENDOFBUFFERCHAR\relax % this is not necessary + \yybyte{}\yybytepure{}% +% + \let\yyreturn\currentyyreturn + } + \endparse \endparseinput {% + \errmessage{internal error.: reading past the end of the input buffer}% + } +} + +\def\yygetpreviousstatedefault{% + \yyclocal=\fgetelemof{yyec}\at\yycp@\relax % yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + \yytextseenlastchar=\yycp@ + \yygetpreviousstat@f@r +} + +\def\yygetpreviousstat@f@r{% + \ifnum\fgetelemof{yyaccept}\at\yycurrentstatelocal=\z@ + % if ( yy_accept[yy_current_state] ) { + \concat\yytextseen\yybyte + \concat\yytextseenpure\yybytepure + \yybyte{}\yybytepure\yybyte + \else % + \ifyyflexdebug\ferrmessage{possible accepting state: \the\yycurrentstatelocal:% + \fgetelemof{yyaccept}\at\yycurrentstatelocal}\fi % TODO: delete + \yyg@yylastacceptingstate=\yycurrentstatelocal + % yyg->yy_last_accepting_state = yy_current_state; + \concat\yytext\yytextseen % yyg->yy_last_accepting_cpos = yy_cp; TODO:????????? + \concat\yytextpure\yytextseenpure % ... ... + \yytextseen=\yybyte + \yytextseenpure=\yybytepure + \yytextbackuptrue + \yybyte{}\yybytepure\yybyte + \yytextlastchar=\yytextseenlastchar % + \fi + \yygpswhile +} + + +\def\yygpswhile{% ... yyllwhile: + \yyact=\fgetelemof{yybase}\at\yycurrentstatelocal\relax% ... ... reusing \yyact ( yy_act = yy_base[yy_current_state] ) + \advance\yyact\yyclocal % ... ... ( yy_act = yy_act + yy_c ) + \ifnum\fgetelemof{yychk}\at\yyact=\yycurrentstatelocal % while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { + \yybreak\yygpsfornext % ... if ( yy_chk[yy_base[yy_current_state] + yy_c] == yy_current_state ) + % ... ... exit the while loop + \else % ... return yy_current_state; + % ... else + \yycurrentstatelocal=\fgetelemof{yydef}\at\yycurrentstatelocal\relax + % yy_current_state = (int) yy_def[yy_current_state]; + \ifnum\yycurrentstatelocal>\YYMAXREALCHAR\relax % if ( yy_current_state >= sizeof( yy_accept ) ) { + \yyclocal=\fgetelemof{yymeta}\at\yyclocal\relax% yy_c = yy_meta[(unsigned int) yy_c]; + \fi % } + \yybreak\yygpswhile % ... goto yyllwhile; + \yycontinue % } +} + +\def\yygpsfornext{% + \yycurrentstatelocal=\fgetelemof{yybase}\at\yycurrentstatelocal\relax + \advance\yycurrentstatelocal\yyclocal + \yycurrentstatelocal=\fgetelemof{yynxt}\at\yycurrentstatelocal\relax + \ifyyflexdebug\ferrmessage{switching to state: \the\yycurrentstatelocal}\fi % TODO: delete + \yyinput +} + +\def\yyfind@ction{% we have to use this macro instead of the + % regular \yyfindaction because we use a stop token (\splitoffend) to terminate + % the `for' loop and are thus `one token behind' by the time this action is taken + % therefore we have to forego the `yy_cp actions' in the original \yyfindaction + \yyact=\fgetelemof{yyaccept}\at\yycurrentstate\relax % yy_act = yy_accept[yy_current_state]; + \ifnum\yyact=\z@ % if ( yy_act == 0 ) { + % yy_cp = yyg->yy_last_accepting_cpos; + \yycurrentstate=\yyg@yylastacceptingstate % yy_current_state = yyg->yy_last_accepting_state; + \yyact=\fgetelemof{yyaccept}\at\yycurrentstate\relax% yy_act = yy_accept[yy_current_state]; + \ifyyflexdebug\ferrmessage{backup.: \the\yytext:\the\yytextseen}\fi + \else + % + \concat\yytext\yytextseen + \concat\yytext\yybyte + \yybyte{}% + \yytextseen{}% + \concat\yytextpure\yytextseenpure + \concat\yyformat\yyformatseen + \concat\yystash\yystashseen + \yytextlastchar=\yytextseenlastchar + \yyfmark=\yyfmarklast + \yysmark=\yysmarklast + \yyformatseen{}% + \yystashseen{}% + % + \fi % } + \concat\yytextseen\yyfutureyytext % ... reinsert the tokens seen by the lexer before + % ... \yygetpreviousaction got rolling + \yyfutureyytext{}% + \yytextbackuptrue +% \YYDOBEFOREACTION % YY_DO_BEFORE_ACTION; + \ifyyflexdebug + \ferrmessage{action.: \the\yyact, state: \the\yycurrentstate\space(\the\yytext) \parsernamespace}% + \fi + \doaction +} diff --git a/support/splint/tex/frontmatter.sty b/support/splint/tex/frontmatter.sty new file mode 100644 index 0000000000..b0071a4bef --- /dev/null +++ b/support/splint/tex/frontmatter.sty @@ -0,0 +1,2 @@ +% this file is left blank on purpose to avoid referencing non-free fonts +% it would contain the \TeX\ macros that generate the cover page for \splint\ manual diff --git a/support/splint/tex/grabstates.sty b/support/splint/tex/grabstates.sty new file mode 100644 index 0000000000..6fa805168a --- /dev/null +++ b/support/splint/tex/grabstates.sty @@ -0,0 +1,69 @@ +% Copyright 2012-2015, 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/>. + +\def\optimization{5} + +\input yycommon.sty % general routines for stack and array access +\input yymisc.sty % helper macros (stack manipulation, table processing, value stack pointers) +\input yyinput.sty % input functions +\input yyparse.sty % parser machinery +\input flex.sty % lexer functions +\input yyfaststack.sty % sped up stack access functions +\input yyboth.sty % parser initialization, optimization +\input yyunion.sty + +\genericparser + name: main, + ptables: cweb/byytab.tex, + ltables: cweb/lstab.tex, + tokens: {}, + asetup: \let\setflexstates\relax, + dsetup: {}, + rsetup: {}, + optimization: \optimizeall;% + +\let\parsernamespace\mainnamespace +\let\yylexreturn\yylexreturnregular + +% main section macro + +\let\nx\noexpand + +\expandafter\def\csname parserstack[b]\endcsname#1#2{% + \basicparserinit\yyparse#1\yyeof\yyeof\endparseinput\endparse + \ifyyparsefail % do nothing if parsing failed + \yybreak{}% + \else % Stage three, process the parsed table + \yybreak{% + \restorecslist{bootstrap}\yyunion + \the\table\relax + }% + \yycontinue +} + +\expandafter\def\csname parserstack[]\endcsname#1#2{% + \basicparserinit\yyparse#1\yyeof\yyeof\endparseinput\endparse + \ifyyparsefail % do nothing if parsing failed + \yybreak{}% + \else % Stage three, process the parsed table + \yybreak{% + \restorecslist{bootstrap}\yyunion + \the\table\relax + }% + \yycontinue +} + +\newwrite\stlist diff --git a/support/splint/tex/limbo.sty b/support/splint/tex/limbo.sty new file mode 100644 index 0000000000..1ab76629a4 --- /dev/null +++ b/support/splint/tex/limbo.sty @@ -0,0 +1,1372 @@ +% Copyright 2012-2015, 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/>. + +% limbo.sty version 2.3 + +\input epsf.tex +\input amssym.def + +\catcode`\@=11 % a name space protection measure (weak) + +% fonts +\font\tenboldi=cmbxti10 +\font\nineboldi=cmbxti9 +\font\eightboldi=cmbxti8 +\font\sevenboldi=cmbxti7 +\font\sixboldi=cmbxti6 +\font\fiveboldi=cmbxti5 + +\font\twelvebi=cmmib10 at 12pt +\font\tenbi=cmmib10 +\font\tencyr=lhr10 +\font\ninebi=cmmib9 +\font\sevenbi=cmmib7 +\font\sixbi=cmmib6 +\font\twelvebsy=cmbsy10 at 12pt +\font\ninebsy=cmbsy9 +\font\sevenbsy=cmbsy7 + +\font\twelvei=cmmi10 at 12pt +\font\ninei=cmmi9 +\font\twelvesy=cmsy10 at 12pt +\font\ninesy=cmsy9 + +\font\twelvetitle=cmssbx12 +\font\tentitle=cmssbx10 +\font\tentitlei=cmssbxo10 +\font\ninetitle=cmssbx9 +\font\eighttitle=cmssbx8 +\font\seventitle=cmssbx7 +\font\titlefrak=eufb10 at 12pt + +\font\tenss=cmss10 +\font\niness=cmss9 +\font\eightss=cmss8 + +\font\twelvetitleit=cmssbxo10 at 12pt +\font\ninetitleit=cmssbxo10 at 9pt +\font\seventitleit=cmssbxo10 at 7pt + +\font\authorfont=cmssqi8 +\font\affiliationfont=cmssq8 +\font\timefont=cmss7 +\font\keywordsfn=cmssbx8 + +\font\tentex=cmtex10 +\font\ninetex=cmtex9 +\font\eighttex=cmtex8 + +\font\inchhigh=cminch +\font\titlefont=cmssdc10 at 40pt + +\font\ninerm=cmr9 +\font\eightrm=cmr8 +\font\sevenrm=cmr7 +\font\ninecyr=lhr9 +\font\eightcyr=lhr8 +\font\sevencyr=lhr7 +\font\sixrm=cmr6 + +\font\ninei=cmmi9 +\font\eighti=cmmi8 +\font\sixi=cmmi6 +\skewchar\ninei='177 \skewchar\eighti='177 \skewchar\sixi='177 + +\font\ninesy=cmsy9 +\font\eightsy=cmsy8 +\font\sixsy=cmsy6 +\skewchar\ninesy='60 \skewchar\eightsy='60 \skewchar\sixsy='60 + +\font\eightss=cmssq8 + +\font\eightssi=cmssqi8 + +\font\twelvebf=cmbx12 +\font\ninebf=cmbx9 +\font\eightbf=cmbx8 +\font\sixbf=cmbx6 + +\font\ninett=cmtt9 +\font\eighttt=cmtt8 +\font\seventt=cmtt7 + +\hyphenchar\tentt=-1 % inhibit hyphenation in typewriter type +\hyphenchar\ninett=-1 +\hyphenchar\eighttt=-1 + +\font\ninesl=cmsl9 +\font\eightsl=cmsl8 +\font\sevensl=cmsl7 + +\font\nineit=cmti9 +\font\eightit=cmti8 +\font\sevenit=cmti7 +\font\sixit=cmti6 +\font\fiveit=cmti5 + +\font\twelvemsam=msam10 at 12pt +\font\tenmsam=msam10 +\font\ninemsam=msam9 +\font\eightmsam=msam8 +\font\sevenmsam=msam7 +\font\sixmsam=msam6 +\font\fivemsam=msam5 + +\font\twelvemsbm=msbm10 at 12pt +\font\tenmsbm=msbm10 +\font\ninemsbm=msbm9 +\font\eightmsbm=msbm8 +\font\sevenmsbm=msbm7 +\font\sixmsbm=msbm6 +\font\fivemsbm=msbm5 + +\font\tenfrak=eufm10 +\font\ninefrak=eufm9 +\font\eightfrak=eufm8 +\font\sevenfrak=eufm7 + +\font\hv=phvr + +\newfam\itbfam +\newfam\frakfam +\newfam\msbmfam +\newfam\msamfam + +% take `<=' and `>=' from Euler ... +% but this will be changed back in the title due to +% the absence of the bold version + +\mathchardef\leq="3\hexnumber@\msamfam36 \let\le=\leq +\mathchardef\geq="3\hexnumber@\msamfam3E \let\ge=\geq +\mathchardef\emptyset="0\hexnumber@\msbfam3F + +% left and right `french quotes' (guillemots); the characters reside in lhr fonts + +\chardef\lqq='375 +\chardef\rqq='376 + +\def\cdotfill{\cleaders\hbox {$\m@th \mkern .5mu\cdot\mkern .5mu$}\hfill} +\def\dinkus{$\ast\ast\ast$} +\def\asterism{\setbox0\hbox{$\ast$}\copy0 \kern-.3\wd0 \raise\ht0 \copy0 \kern-.3\wd0 \copy0 } + +\newskip\ttglue +\def\tenpoint{\def\rm{\fam0\tenrm}% + \textfont0=\tenrm \scriptfont0=\sevenrm \scriptscriptfont0=\fiverm + \textfont1=\teni \scriptfont1=\seveni \scriptscriptfont1=\fivei + \textfont2=\tensy \scriptfont2=\sevensy \scriptscriptfont2=\fivesy + \textfont3=\tenex \scriptfont3=\tenex \scriptscriptfont3=\tenex + \def\it{\fam\itfam\tenit}% + \textfont\itfam=\tenit\scriptfont\itfam=\sevenit + \scriptscriptfont\itfam=\fiveit + \def\itbold{\fam\itbfam\tenboldi}% + \textfont\itbfam=\tenboldi\scriptfont\itfam=\sevenboldi + \scriptscriptfont\itbfam=\fiveboldi + \def\sl{\fam\slfam\tensl}% + \textfont\slfam=\tensl + \def\bf{\fam\bffam\tenbf}% + \textfont\bffam=\tenbf \scriptfont\bffam=\sevenbf + \scriptscriptfont\bffam=\fivebf + \def\tt{\fam\ttfam\tentt + \let\{=\LB % left brace in a string + \let\}=\RB % right brace in a string + }% + \def\ttex{\tentex + \let\{=\LB % left brace in a string + \let\}=\RB % right brace in a string + }% + \def\ttl{\let\it\tentitlei\let\sl\tentitlei\tentitle}% + \def\ssf{\tenss}% + \textfont\ttfam=\tentt + \tt \ttglue=.5em plus.25em minus.15em + \def\Bbb{\fam\msbmfam\tenmsbm}% + \textfont\msbmfam=\tenmsbm\scriptfont\msbmfam=\sevenmsbm \scriptscriptfont\msbmfam=\fivemsbm + \textfont\msamfam=\tenmsam\scriptfont\msamfam=\sevenmsam + \scriptscriptfont\msamfam=\fivemsam + \textfont\frakfam=\tenfrak + \def\frak##1{{\fam\frakfam\tenfrak ##1}}% + \normalbaselineskip=12pt + \let\sc=\eightrm + \let\mc=\ninerm + \let\cyr=\tencyr + \let\big=\tenbig + \setbox\strutbox=\hbox{\vrule height8.5pt depth3.5pt width0pt}% + \normalbaselines\rm} + +\def\ninepoint{\def\rm{\fam0\ninerm}% + \textfont0=\ninerm \scriptfont0=\sixrm \scriptscriptfont0=\fiverm + \textfont1=\ninei \scriptfont1=\sixi \scriptscriptfont1=\fivei + \textfont2=\ninesy \scriptfont2=\sixsy \scriptscriptfont2=\fivesy + \textfont3=\tenex \scriptfont3=\tenex \scriptscriptfont3=\tenex + \def\it{\fam\itfam\nineit}% + \textfont\itfam=\nineit\scriptfont\itfam=\sixit + \def\itbold{\fam\itbfam\nineboldi}% + \textfont\itbfam=\nineboldi\scriptfont\itfam=\sixboldi + \def\sl{\fam\slfam\ninesl}% + \textfont\slfam=\ninesl + \def\bf{\fam\bffam\ninebf}% + \textfont\bffam=\ninebf \scriptfont\bffam=\sixbf + \scriptscriptfont\bffam=\fivebf + \def\tt{\fam\ttfam\ninett + \let\{=\LB % left brace in a string + \let\}=\RB % right brace in a string + }% + \def\ttex{\ninetex + \let\{=\LB % left brace in a string + \let\}=\RB % right brace in a string + }% + \def\ttl{\let\it\ninetitleit\let\sl\ninetitleit\ninetitle}% + \def\ssf{\niness}% + \textfont\ttfam=\ninett + \tt \ttglue=.5em plus.25em minus.15em + \def\Bbb{\fam\msbmfam\ninemsbm}% + \textfont\msbmfam=\ninemsbm\scriptfont\msbmfam=\sixmsbm \scriptscriptfont\msbmfam=\fivemsbm + \textfont\msamfam=\ninemsam\scriptfont\msamfam=\sixmsam + \scriptscriptfont\msamfam=\fivemsam + \textfont\frakfam=\ninefrak + \def\frak##1{{\fam\frakfam\ninefrak ##1}}% + \normalbaselineskip=11pt + \let\sc=\sevenrm + \let\mc=\eightrm + \let\cyr=\ninecyr + \let\big=\ninebig + \setbox\strutbox=\hbox{\vrule height8pt depth3pt width0pt}% + \normalbaselines\rm} + +\def\eightpoint{\def\rm{\fam0\eightrm}% + \textfont0=\eightrm \scriptfont0=\sixrm \scriptscriptfont0=\fiverm + \textfont1=\eighti \scriptfont1=\sixi \scriptscriptfont1=\fivei + \textfont2=\eightsy \scriptfont2=\sixsy \scriptscriptfont2=\fivesy + \textfont3=\tenex \scriptfont3=\tenex \scriptscriptfont3=\tenex + \def\it{\fam\itfam\eightit}% + \def\itbold{\fam\itbfam\eightboldi}% + \textfont\itfam=\eightit + \def\sl{\fam\slfam\eightsl}% + \textfont\slfam=\eightsl + \def\bf{\fam\bffam\eightbf}% + \textfont\bffam=\eightbf \scriptfont\bffam=\sixbf + \scriptscriptfont\bffam=\fivebf + \def\tt{\fam\ttfam\eighttt + \let\{=\LB % left brace in a string + \let\}=\RB % right brace in a string + }% + \def\ttex{\eighttex + \let\{=\LB % left brace in a string + \let\}=\RB % right brace in a string + }% + \textfont\ttfam=\eighttt + \tt \ttglue=.5em plus.25em minus.15em + \def\Bbb{\fam\msbmfam\eightmsbm}% + \textfont\msbmfam=\eightmsbm\scriptfont\msbmfam=\sixmsbm \scriptscriptfont\msbmfam=\fivemsbm + \textfont\msamfam=\eightmsam\scriptfont\msamfam=\sixmsam + \scriptscriptfont\msamfam=\fivemsam + \textfont\frakfam=\eightfrak + \def\frak##1{{\fam\frakfam\eightfrak ##1}}% + \normalbaselineskip=9pt + \let\sc=\sixrm + \let\mc=\sevenrm + \let\cyr=\eightcyr + \let\big=\eightbig + \setbox\strutbox=\hbox{\vrule height7pt depth2pt width0pt}% + \normalbaselines\rm} + +\def\sevenpoint{\def\rm{\fam0\sevenrm}% + \textfont0=\sevenrm \scriptfont0=\sixrm \scriptscriptfont0=\fiverm + \textfont1=\seveni \scriptfont1=\sixi \scriptscriptfont1=\fivei + \textfont2=\sevensy \scriptfont2=\sixsy \scriptscriptfont2=\fivesy + \textfont3=\tenex \scriptfont3=\tenex \scriptscriptfont3=\tenex + \def\it{\fam\itfam\sevenit}% + \def\itbold{\fam\itbfam\sevenboldi}% + \textfont\itfam=\sevenit + \def\sl{\fam\slfam\sevensl}% + \textfont\slfam=\sevensl + \def\bf{\fam\bffam\sevenbf}% + \textfont\bffam=\sevenbf \scriptfont\bffam=\sixbf\scriptscriptfont\bffam=\fivebf + \def\tt{\fam\ttfam\seventt + \let\{=\LB % left brace in a string + \let\}=\RB % right brace in a string + }% + \textfont\ttfam=\seventt + \tt \ttglue=.5em plus.25em minus.15em + \def\Bbb{\fam\msbmfam\sevenmsbm}% + \textfont\msbmfam=\sevenmsbm\scriptfont\msbmfam=\sixmsbm \scriptscriptfont\msbmfam=\fivemsbm + \textfont\msamfam=\sevenmsam\scriptfont\msamfam=\sixmsam + \scriptscriptfont\msamfam=\fivemsam + \textfont\frakfam=\sevenfrak + \def\frak##1{{\fam\frakfam\sevenfrak ##1}}% + \normalbaselineskip=8pt + \let\sc=\sixrm + \let\mc=\sixrm + \let\big=\sevenbig + \setbox\strutbox=\hbox{\vrule height6pt depth2pt width0pt}% + \normalbaselines\rm} + +% temporary registers + +\input trt1.sty + +% we can prevent acrobat from defaulting to +% the "shrink to printable area" setting, which causes an 8.5"\times11" page to shrink +% by about 6\% to fit onto the printable region of the physical printer; +% this macro was contributed by Jeff Norden. + +\ifx\pdfcatalog\UNDEFINED\else + \pdfcatalog{/ViewerPreferences<</PrintScaling/None>>}% +\fi + +% a slightly involved way of determining whether we are making a pdf file is +% due to the fact that pdftex can output dvi files as well. + +\newif\ifmakepdf + +\ifx\pdfoutput\undefined + \makepdffalse +\else + \ifnum\pdfoutput>\z@ + \makepdftrue + \else + \makepdffalse + \fi +\fi + +% cleaning up whitespace + +\newif\ifspaceleft + +\def\removewhitespace{% a macro that removes glue, kerns, and + % penalties before the current point + \loop\spaceleftfalse\unwhitespaceonce\ifspaceleft\repeat +} + +\def\unwhitespaceonce{% +\ifhmode + \ifdim\lastskip=\z@\else\unskip\spacelefttrue\fi + \ifdim\lastkern=\z@\else\unkern\spacelefttrue\fi + \ifnum\lastpenalty=\z@\else\unpenalty\spacelefttrue\fi +\fi} + +% color management + +% remember the cmyk color in an impossible control sequence + +\def\colordef#1#2{\expandafter\def\csname cmykc@l@r #1\endcsname{#2}} + +% color switch: we maintain our own color stack for pdf output; +% newer versions of pdf\TeX\ have `proper' color stack primitives +% which provide a more reliable implementation (across page breaks +% and inside insertions, for example) + +\def\colorset#1{\begingroup + \ifmakepdf + \expandafter\let\expandafter\currentc@l@r\csname cmykc@l@r #1\endcsname + \edef\next{\noexpand\pdfliteral{\csname cmykc@l@r #1\endcsname\space k}}\next + \else + \special{ps:gsave}% + \edef\next{\special{ps:\csname cmykc@l@r #1\endcsname\space setcmykcolor}}\next + \fi +} + +\def\currentc@l@r{1 1 1 1} % start out black + +\def\quickcolordef#1#2{\colordef{#1}{#2}% + \expandafter\def\csname color#1\endcsname##1{\colorset{#1}##1\restorecolor}} + +\def\grayset#1{\begingroup + \ifmakepdf + \def\currentc@l@r##1k{#1 g}% so we can use \restoreco... + \pdfliteral{#1 g}% + \else + \special{ps:gsave}\special{ps:#1 setgray}% + \fi +} + +\def\restorecolor{\endgroup + \ifmakepdf + \expandafter\pdfliteral\expandafter{\currentc@l@r\space k}% + \else + \special{ps:grestore}% + \fi +} + +% macros to provide pdf references to outside documents as well as inside the code + +\def\locallink#1{% + \ifmakepdf\colorset{link}\pdfstartlink attr {/Border [0 0 0]} goto name {#1}\fi} + +\def\exlinkpage#1#2#3{\colorset{link}% + \ifmakepdf\pdfstartlink attr {/Border [0 0 0]} goto file {#1} page #2 {#3}\fi} + +\def\endlink{\ifmakepdf\pdfendlink\restorecolor\fi} + +\def\namedspot#1{\ifmakepdf + % raise the reference to make sure that the viewer window shows the + % whole line in which the reference occurs + \raise\ht\strutbox\vbox to 0pt{\vss\hbox to 0pt{\pdfdest name {#1} xyz}}% +\fi} + +% macros to typeset hex values in customized form (useful when typesetting embedded code) + +% the line translator: take a sequence of tokens and translate it into another sequence +% #1 is the sequence of tokens (will be expanded) to insert at the beginning +% #2 is the sequence of tokens (will be expanded) to insert before every token in the sequence +% #3 is the first sequence of tokens (will be expanded) to insert between tokens in the sequence +% #4 is the second sequence of tokens (will be expanded) to insert between tokens in the sequence +% #5 is the sequence of tokens (will be expanded) to insert at the end +% #6 is the command to execute after each token +% #7 is original sequence +% #8 is the resulting sequence + +\def\linetranslator#1#2#3#4#5#6:#7>#8{% + \def\ins@rt{#2}\def\insert@{#3}\def\@insert{#4}% + \def\@nd{#5}\def\c@mmand{#6}\let\t@kens#8% + \edef\next{\t@kens{\the\t@kens#1}}\next + \expandafter\linetr@nslator\the#7\end} + +\def\linetr@nslator#1#2{% + \ifx#1\end + \let\next\relax % no more tokens left + \else + \ifx#2\end % #1 is the last token + \edef\next{\t@kens{\the\t@kens\ins@rt#1\@nd}}\next + \else + \edef\next{\t@kens{\the\t@kens\ins@rt#1\insert@\@insert}}\next + \c@mmand + \fi + \let\next\linetr@nslator + \fi\next#2 +} + +% the mask translator: take a sequence of pairs {length:number}{contents} and translate it into another sequence +% #1 is the sequence of tokens (will be expanded) to insert at the beginning +% #2 is the sequence of tokens (will be expanded) to insert before every pair in the sequence +% #3 is the first sequence of tokens (will be expanded) to insert between pairs in the sequence +% #4 is the second sequence of tokens (will be expanded) to insert between pairs in the sequence +% #5 is the sequence of tokens (will be expanded) to insert at the end +% #6 is the command to execute after each pair +% #7 is original sequence +% #8 is the resulting sequence + +\def\masktranslator#1#2#3#4#5#6:#7>#8{% + \def\ins@rt{#2}\def\insert@{#3}\def\@insert{#4}% + \def\@nd{#5}\def\c@mmand{#6}\let\t@kens#8% + \edef\next{\t@kens{\the\t@kens#1}}\next + \m@sktranslator#7{"40000000}\relax\relax} + +\def\m@sktranslator#1#2#3{% + \ifnum#1<"40000000 % only happens when there are no pairs + \ifnum#3<"40000000 % not the last pair + \edef\next{\t@kens{\the\t@kens\ins@rt{#1}{#2}\insert@\@insert}}\next + \c@mmand + \let\next\m@sktranslator + \else + \edef\next{\t@kens{\the\t@kens\ins@rt{#1}{#2}\@nd}}\next + \let\next\m@sktr@nslator + \fi + \else + \let\next\m@sktr@nslator + \fi + \next{#3}% +} + +\def\m@sktr@nslator#1{} + +% binary converter + +\def\binary#1{% + \ifx#1\end + \let\next\relax + \else + \bin@ry#1\let\next\binary + \fi\next} + +\let\bits\toksa % storage for binary conversion bits +\newtoks\bytes % storage for the binary representation +\let\quotient\tempca +\let\oldquotient\tempcb + +\def\bin@ry#1{\tempcc=4 \quotient="#1 \oldquotient=\quotient +\loop \divide\quotient by2 \multiply\quotient by2 \advance\oldquotient by-\quotient + \advance\tempcc by\m@ne + \edef\next{\bits{\the\oldquotient\the\bits}}\next + \divide\quotient by2 \oldquotient=\quotient +\ifnum\tempcc > \z@ +\repeat +\edef\next{\bytes{\the\bytes\the\bits}}\next +\bits{}} + +% display macros: +% +% o registers + +\newtoks\digittable % the table representing the register +\newcount\columncount % counter for the current column + +% o fonts + +\font\fivessb=phvb at4pt + +% o generic control sequences + +\def\incrementcc{\advance\columncount by\@ne} +\def\decrementcc{\advance\columncount by\m@ne} + +% o mask highlighting + +% the strange looking definition of \m@skspan originates from \multispan in plain.tex: +% \newcount\mscount +% \def\multispan#1{\omit \mscount#1\relax +% \loop\ifnum\mscount>\@ne \sp@n\repeat} +% \def\sp@n{\span\omit\advance\mscount\m@ne} +% +% the number of `physical' columns to span is (2 * columns - 1) due to the fact that we +% have to span the gaps between columns as well. + +\def\m@skspan#1#2{% + \multispan{#1\advance\mscount by\mscount\advance\mscount by-1}{\vrule\highltcl{\leaders\hrule height 4pt\hfil}\vrule}% +} + +% o mask underlining + +\def\m@sksp@n#1#2{% + \multispan{#1\advance\mscount by\mscount\advance\mscount by-1}{\hrulefill}% +} + +% o mask legend typesetting + +\def\m@sklegend#1#2{% + \multispan{#1\advance\mscount by\mscount\advance\mscount by-1}{\hfil\lgndcl{\fivessb#2}\hfil}% +} + +% o displaying each digit + +\def\dgtdispl@y#1#2{% + \ifx#20% + \let\colorbg\lightcl\let\colord\darkcl + \else + \let\colorbg\darkcl\let\colord\lightcl + \fi + \vrule\colorbg{\vrule height4pt width 12.5pt}% + \llap{\raise.6pt\hbox{\colord{\fivessb#1}$\,$}}\vrule +} + +% o typesetting space between digits + +\def\c@lumnspacer#1{\tempca#1\tempcb\tempca\divide\tempca by8\multiply\tempca by8 + \ifnum\tempca=\tempcb + \middlediamond + \else + \tempca#1\tempcb\tempca\divide\tempca by4\multiply\tempca by4 + \ifnum\tempca=\tempcb + \middledot + \else + \hfil + \fi + \fi} + +% oo dimond to separate bytes + +\def\middlediamond{\setbox0=\hbox{$\scriptscriptstyle\diamond$}\tempda=4pt \advance\tempda by-\ht0 + \divide\tempda by2 \hss\raise\tempda\box0\hss}% + +% oo dot to separate nybbles + +\def\middledot{\setbox0=\hbox{.}\tempda=4pt \advance\tempda by-\ht0 + \divide\tempda by2 \hss\raise\tempda\box0\hss}% + +% o put it all together + +\let\stcr\cr % so that this can be used inside \tabalign which redef's \cr + +\def\regdisplay#1#2{{% + \binary#1\end + \linetranslator{}{\hrulefill\noexpand\eatone}{&$\,\,$}{&}{\stcr}{\incrementcc}:\bytes>\digittable + \linetranslator{}{\noexpand\dgtdispl@y{\the\columncount}}{&\noexpand\c@lumnspacer{\the\columncount}}{&}% + {\stcr}{\decrementcc}:\bytes>\digittable + \masktranslator{}{\noexpand\m@sksp@n}{&\hfil}{&}{\stcr}{\relax}:{#2}>\digittable + \masktranslator{}{\noexpand\m@skspan}{&\hfil}{&}{\stcr}{\relax}:{#2}>\digittable + \masktranslator{}{\noexpand\m@sksp@n}{&\hfil}{&}{\stcr}{\relax}:{#2}>\digittable + \expandafter\digittable\expandafter{\the\digittable\noalign{\vskip-3.8pt}}% + \masktranslator{}{\noexpand\m@sklegend}{&\hfil}{&}{\stcr}{\relax}:{#2}>\digittable + \vbox{\offinterlineskip + \halign{&##\stcr + \the\digittable + } + }% +}} + +% an alternate display + +\def\altmiddledot{\setbox0=\hbox{.}% + \tempda=\ht\thezero \advance\tempda by-\ht0 + \divide\tempda by2 \advance\tempda by -\dp\thezero + $\,$\raise\tempda\box0$\,$% +} + +\def\altmiddlediamond{\setbox0=\hbox{$\scriptscriptstyle\diamond$}% + \tempda=\ht\thezero \advance\tempda by-\ht0 + \divide\tempda by2 \advance\tempda by -\dp\thezero + \hss\raise\tempda\box0\hss +} + +\def\altdgtdispl@y#1#2{% + \ifx#20% + \let\colorbg\lightcl\let\colord\darkcl + \else + \let\colorbg\darkcl\let\colord\lightcl + \fi + \setbox0=\hbox{$\,$0$\,$}\tempda\ht0 + \advance\tempda by 2pt \ht0\tempda + \vrule\colorbg{\lower1pt\hbox{\vrule height\ht0 depth\dp0 width \wd0}}% + \llap{\colord{\raise.5pt\hbox{\fivessb#1$\,$}}}\vrule +} + +\def\altc@lumnspacer#1{\tempca#1\tempcb\tempca + \divide\tempca by4\multiply\tempca by4 + \ifnum\tempca=\tempcb + \ % + \else + \kern1pt% + \fi +} + +\def\bytedisplay#1{{% + \binary#1\end + \linetranslator{}{\hrulefill\noexpand\eatone}{&\hfil}{&}{\stcr}{\incrementcc}:\bytes>\digittable + \linetranslator{}{\noexpand\altdgtdispl@y{\the\columncount}}{&\noexpand\altc@lumnspacer{\the\columncount}}{&}% + {\stcr}{\decrementcc}:\bytes>\digittable + \linetranslator{}{\hrulefill\noexpand\eatone}{&\hfil}{&}{\stcr}{\incrementcc}:\bytes>\digittable + \lower\dp\thezero\vbox{\offinterlineskip + \halign{&##\stcr + \the\digittable + } + }% +}} + +\quickcolordef{peach}{0 0.06 0.14 0} +\quickcolordef{corn}{0 0.06 0.63 0.02} +\quickcolordef{sandybrown}{0 0.33 0.61 0.04} +\quickcolordef{darkwood}{0 0.29 0.5 0.48} +\quickcolordef{link}{0 0 1 0.30} + +\def\colorblack#1{\grayset{0}#1\restorecolor} +\def\colorwhite#1{\grayset{1}#1\restorecolor} +\def\colorgray#1{\grayset{.5}#1\restorecolor} + +\newif\iffullcolorpalette +\fullcolorpalettetrue + +\iffullcolorpalette + \let\lightcl=\colorpeach + \let\shadedcl=\colorcorn + \let\highltcl=\colorgray + \let\lgndcl=\colorwhite +\else + \let\lightcl=\colorwhite + \let\shadedcl=\colorgray + \let\highltcl=\colorwhite + \let\lgndcl=\colorblack +% \let\colorlinkstart=\begingroup +% \let\colorlinkend=\endgroup +\fi + \let\darkcl=\colorblack + +% macros to typeset the hex numbers in `graphic' format + +\newtoks\registerlegend + +\def\registerdisplay#1\end{\edef\next{\the\registerlegend}% + \ifx\next\empty + \edef\next{\noexpand\bytedisplay{#1}}\next + \else + \edef\next{\noexpand\regdisplay{#1}{\the\registerlegend}}\next + \fi +} + +\newbox\thezero + +\setbox\thezero=\hbox{\lower1pt\hbox{\vbox{\offinterlineskip +\halign{#&$\,$#$\,$&#\cr +\noalign{\hrule} +\omit\vrule height1pt&&\omit\vrule height1pt\cr +\vrule&\phantom0&\vrule\cr +\omit\vrule height1pt&&\omit\vrule height1pt\cr +\noalign{\hrule} +}}}} + +\def\texbinary{\global\let\oldT\T + \global\def\T##1{{\let\end\relax\let\^\registerdisplay##1\end{\tt :}\let\^\hexify##1\end}}} + +\def\endtexbinary{\global\let\T\oldT} + +\def\hexify#1\end{\hbox{{\tt #1}$_{\scriptscriptstyle1\kern-.7pt6}$}} + +% verbatim listing macros borrowed (with changes) from The TeXbook + +\newcount\democodelc + +\chardef\other=12 +\def\ttverbatim{\begingroup + \catcode`\\=\other + \catcode`\{=\other + \catcode`\}=\other + \catcode`\$=\other + \catcode`\&=\other + \catcode`\#=\other + \catcode`\%=\other + \catcode`\~=\other + \catcode`\_=\other + \catcode`\|=\other + \obeyspaces \obeylines \tt \ttglue=.5em plus.25em minus.15em } + +{\catcode`\^=\active \catcode`\*=7 \obeylines + \gdef^{\leavevmode\ttverbatim \spaceskip\ttglue \def**M{\endgroup\cr}\let^=\endgroup}} + +\def\beginlines{\begingroup\parindent0pt \obeylines \everypar{\strut}\catcode`\^=\active} +\def\endlines{\endgroup} + +\def\paddednumber#1{\ifnum #1 < 10 0\number#1\relax\else \number#1\fi} + +% demo code display +% **H will produce a `|', **K can be used as an escape character, **L and **N +% can be used i place of left and right braces to provide some control + +{\catcode`\ =\active\gdef {\phantom{\char"20\relax}}\catcode`\^^H=\active\gdef^^H{\yl}}% + +\newif\ifnumberlines + +\def\begindemo{% + \medskip + \bgroup + \def\linenoup{% + \global\advance\democodelc by1 + \ifnumberlines{\sevenrm\paddednumber\democodelc}\fi} + \def\nooutput{\omit\hfil{\sevenrm\strut[more code $\ldots$]}\hfil\cr\noalign{\kern3pt}} + \catcode`\^=\active\democodelc=0 \catcode`\*=7 + \chardef\*=`\*% + \catcode`\^^H=\active % ^^H + \catcode`\^^K=0 \catcode`\^^L=1 \catcode`\^^N=2 + \tabskip=0pt plus 1 fill + \halign \demoastyle\bgroup\linenoup\hskip\demomargin ##\hfil\hskip\demomargin% + \ifnumberlines{\sevenrm\paddednumber\democodelc}\fi\cr% +} + +\def\enddemo{\egroup\egroup\medskip\noindent} + +\newskip\demomargin +\demomargin=3em + +\def\demoastyle{to\hsize} + +% macros to provide some primitive alignment + +\def\texalignment{\setbox0\lastbox\setbox0\lastbox\unkern\begingroup\settabs 3 \columns +\let\C\tabC\let\8\tabalign\def\5{\relax\ifmmode\oopsamp\else\clearamp\fi}\def\6{\strut\cr}} + +\def\oopsamp{$&$} +\def\clearamp{&} + +\def\texalignmentshort{\setbox0\lastbox\setbox0\lastbox\unkern\begingroup\settabs 2 \columns + \let\C\tabC\let\8\tabalign\def\5{\ifmmode\oopsamp\else\clearamp\fi}\def\6{\strut\cr}} + +\def\endtexalignment{\vskip-\baselineskip\strut\endgroup} + +\def\eatcr#1\6{\ignorespaces} + +\newtoks\postlimbotoks + +\def\postlimbostuff{% +} + +\def\picture#1{\ifmakepdf\pdfximage{#1.pdf}\pdfrefximage\pdflastximage + \else + \epsfbox{#1.eps}\fi +} + +\let\yl| % to use in \TeX\ mode instead of `|' +\def\greaterthan{>} % CTANGLE always leaves a space after `>' in the output which interferes with some macros + +% redefinitions of various CWEB macros; + +% macros that provide a way to customize printing of reserved words + +\newtoks\tempseq +\tempseq={RVD} +\let\oldamp\& +\let\oldoneletterid\| +\def\replaceunderscore#1{\let\next\replaceunderscore + \ifx#1\_\tempseq=\expandafter{\the\tempseq x}\else + \ifx#1\#\tempseq=\expandafter{\the\tempseq H}\else + \ifx#1\end\let\next\relax\else\tempseq=\expandafter{\the\tempseq #1}\fi + \fi + \fi\next} +\def\reservedid#1{{\replaceunderscore#1\end + \expandafter\let\expandafter\newseq\csname\the\tempseq\endcsname + \ifx\relax\newseq\oldamp{#1}\else\newseq\fi}} + +\def\reservedoneletterid#1{{% + \expandafter\let\expandafter\newseq\csname\the\tempseq\string#1\endcsname + \ifx\relax\newseq\oldoneletterid{#1}\else\newseq\fi}} + +\def\defreserved#1{% + \expandafter\def\csname\the\tempseq #1\endcsname +} + +\let\&\reservedid +\let\|\reservedoneletterid + +% cweb macros adopted to making typesetting languages other than C possible: Makefile and linker scripts. + +\tempca=\catcode`\^^I% remember the old catcode +\catcode`\^^I=\active +\def\vb{\begingroup\catcode`\^^I=\active\vvb} % give the tab a chance to change its catcode before the rest is scanned +\def\vvb#1{{% + \hbox{\vbox{\ttex%\tt + \let\\=\BS % backslash in a string + \let\{=\LB % left brace in a string + \let\}=\RB % right brace in a string + \let\~=\TL % tilde in a string + %\let\ =\space % space in a string + \def\ {\phantom{0}}% + \let\_=\UL % underline in a string + \let\&=\AM % ampersand in a string + \let\^=\CF % circumflex in a string + \let\$=\oldmathS % dollar sign + \def^^I{$\llcorner$&$\lrcorner$}% a tab is a tab + \tabalign{}#1\cr}}}\endgroup} % verbatim string +\catcode`\^^I=\tempca + +\def\hex{\hbox{\tt\aftergroup}\aftergroup\hexsubscript} +\def\hexsubscript{\hbox{$_{\scriptscriptstyle1\kern-.7pt6}$}} +\let\K=\Leftarrow +\setbox\MGbox=\hbox{\hbox{\ninei\char'053}} +\def\R{\hbox{$^{\rm not}$}} +\let\CM\lnot +\def\MRL#1{\KK#1}\def\KK#1#2{\buildrel\;{\let\OR\lor\scriptscriptstyle#1}\over#2} +\def\C#1{\5\5\quad$\triangleright\,${\rm #1}$\,\triangleleft$} +\let\Z=\leq \let\G=\geq +\let\E== + +\def\tabC#1{\quad$\triangleright\,${\cmntfont#1}$\,\triangleleft$} + +% better `hash' + +\let\oldhash\# +\def\#{\lower.5pt\hbox{\.{\oldhash}}} + +\def\.#1{\leavevmode\hbox{\tt % typewriter type for strings + \let\\=\BS % backslash in a string + \let\{=\LB % left brace in a string + \let\}=\RB % right brace in a string + \let\~=\TL % tilde in a string + \let\ =\SP % space in a string + %\let\_=\UL % underline in a string + \let\&=\AM % ampersand in a string + \let\^=\CF % circumflex in a string + \let\uscore\_\chardef\_=`\_% + #1\kern.05em}} + +% macros to change the appearance of section headers + +\outer\def\N#1#2#3.{% beginning of starred section + \ifacro{\toksF={}\makeoutlinetoks#3\outlinedone\outlinedone}\fi + \gdepth=#1\gtitle={#3}\MN{#2}% + \ifon\ifnum#1<\secpagedepth \vfil\eject % force page break if depth is small + \else\vfil\penalty-100\vfilneg\vskip\intersecskip\fi\fi + \message{*\secno} % progress report + \def\stripprefix##1>{}\def\gtitletoks{#3}% + \edef\gtitletoks{\expandafter\stripprefix\meaning\gtitletoks}% + \edef\next{\write\cont{%\noexpand\noexpand\noexpand\eatone{\noexpand\meaning\noexpand\ZZ}% + \noexpand\noexpand\noexpand % AS this is a (sort of) bug in cwebmac.tex + % as long as the index is output (i.e. ...\eject) + % before all the sections this is unnecessary + % uncomment the line after the brace to see what \ZZ + % expands to in case of weird errors + \ZZ{\gtitletoks}{#1}{\secno}% write to contents file + {\noexpand\the\pageno}{\the\toksE}}}\next % \ZZ{title}{depth}{sec}{page}{ss} + \ifpdftex\expandafter\xdef\csname curr#1\endcsname{\secno}% + \ifnum#1>0\countB=#1 \advance\countB by-1 + \advancenumber{chunk\the\countB.\expnumber{curr\the\countB}}\fi\fi + \ifpdf\special{pdf: outline #1 << /Title (\the\toksE) /Dest + [ @thispage /FitH @ypos ] >>}\fi + \ifon\startsection{\ttl#3.\ }\ignorespaces} % changed the font; AS + +\let\oldN\N + +\outer\def\textN#1#2#3.{% beginning of starred section in `text' mode + \ifacro{\toksF={}\makeoutlinetoks#3\outlinedone\outlinedone}\fi + \gdepth=#1\gtitle={#3}\MN{#2}% + \ifon + \ifnum#1<2 + \vfil\eject % force page break for chapters + \else + \vskip0pt plus 3.5\baselineskip\penalty-100\vskip0pt plus -3.5\baselineskip\vskip\intersecskip % no page break + \fi + \fi + \message{*\secno} % progress report + \def\stripprefix##1>{}\def\gtitletoks{#3}% + \edef\gtitletoks{\expandafter\stripprefix\meaning\gtitletoks}% + \edef\next{\write\cont{%\noexpand\noexpand\noexpand\eatone{\noexpand\meaning\noexpand\ZZ}% + \noexpand\noexpand\noexpand % AS this is a (sort of) bug in cwebmac.tex + % as long as the index is output (i.e. ...\eject) + % before all the sections this is unnecessary + % uncomment the line after the brace to see what \ZZ + % expands to in case of weird errors + \ZZ{\gtitletoks}{#1}{\secno}% write to contents file + {\noexpand\the\pageno}{\the\toksE}}}\next % \ZZ{title}{depth}{sec}{page}{ss} + \ifpdftex\expandafter\xdef\csname curr#1\endcsname{\secno}% + \ifnum#1>0\countB=#1 \advance\countB by-1 + \advancenumber{chunk\the\countB.\expnumber{curr\the\countB}}\fi\fi + \ifpdf\special{pdf: outline #1 << /Title (\the\toksE) /Dest + [ @thispage /FitH @ypos ] >>}\fi + \ifon\startsection{\ttl#3}\smallskip\noindent\ignorespaces} + +\outer\def\textM#1{\MN{#1}\ifon\vskip0pt plus 3\baselineskip\penalty-100\vskip0pt plus -3\baselineskip % no page break + \vskip\intersecskip\startsection\ignorespaces} + +\def\MN#1{\par % common code for \M, \N + {\xdef\secstar{#1}\let\*=\empty\xdef\secno{#1}}% remove \* from section name + \ifx\secno\secstar \onmaybe \else\ontrue \fi + \mark{{\secno}{\the\gdepth}{\the\gtitle}}} % remove the annoying + % `paragraph' sign; AS + +% a new start section macro: fix the extra space bug and push the setion number to the margins + +\def\stseclap{\rightskip=0pt % get out of C mode (cf. \B) + \sfcode`;=1500 \pretolerance 200 \hyphenpenalty 50 \exhyphenpenalty 50 + \noindent{\let\*=\lapstar\llap{\tentitle\secstar\quad}}% push it to the margins + \ifpdftex\smash{\raise\baselineskip\hbox to0pt{% + \let\*=\empty\ifmakepdf\pdfdest num \secstar fith\fi}}% this space is a bug in the original cwebmac.tex; AS + \else\ifpdf\smash{\raise\baselineskip\hbox to0pt{% + \let\*=\empty\special{% + pdf: dest (\romannumeral\secstar) [ @thispage /FitH @ypos ]}}}\fi\fi} + +\let\startsection\stseclap + +% make page and sectoin number hang in the margins; \quad is chosen to +% be consistent with section appearance; the page numbers are printed +% in old-style numerals; + +\def\lheader{\headertrue\llap{\mainfont\oldstyle\the\pageno\tentitle\quad}\eightpoint\rm\grouptitle + \hfill\title\rlap{\tentitle\quad\tenpoint$^{\hbox{\sevenrm\topsecno}}_{\hbox{\sevenrm\botsecno}}$}} % top line on left-hand pages +\def\rheader{\headertrue +\llap{\tenpoint$^{\hbox{\sevenrm\topsecno}}_{\hbox{\sevenrm\botsecno}}$\tentitle\quad}% +\eightpoint\rm\title\hfill + \grouptitle\rlap{\tentitle\quad\mainfont\oldstyle\the\pageno}} % top line on right-hand pages + +\def\botsecno{\expandafter\takeone\botmark} % the first section on the + % next page + +% from time to time, entries must be omitted from the index; +% the macros below implement a mechanism to do that + +\newif\ifisindexable + +\def\setindexable#1{% + \isindexabletrue + \def\next{#1}% + \expandafter\s@t@ndexable\unindexable.\end +} + +\def\s@t@ndexable#1#2\end{% + {% + \def\ifisindexable{#1}% + \ifx\ifisindexable\next + \yybreak{\aftergroup\isindexablefalse\aftergroup\eattoend}% + \else + \def\ifisindexable{#2}% + \ifx\ifisindexable\dotcontainer + \yybreak@{\aftergroup\eattoend}% + \else + \yybreak@{\aftergroup\s@t@ndexable}% + \fi + \yycontinue + }% + #2\end +} + +\def\inxmod{% + \write\cont{} % ensure that the contents file isn't empty + \write\cont{\catcode `\noexpand\@=12\relax} % \makeatother + \closeout\cont % the contents information has been fully gathered + \message{Index:} + \medskip + \eightpoint\raggedright + \fnotesstart=2 + \fnotesspan=1 + \noofcolumns=3 + \icgap=5pt% + \linecount=3 + \setmcparams + \dsskip=0pt% + \adjskip=0pt plus 9pt% + \ifx\unindexable\UNDEFINED + \def\unindexable{{$\TeXx$}{$\TeXa$}{$\TeXb$}{$\TeXf$}{$\TeXao$}{$\TeXfo$}}% + \else + \expandafter\def\expandafter\unindexable\expandafter{\unindexable + {$\TeXx$}{$\TeXa$}{$\TeXb$}{$\TeXf$}{$\TeXao$}{$\TeXfo$}% + }% + \fi + \def\I##1, ##2.{% + {% + \setindexable{##1}% + \ifisindexable + \else + \aftergroup\eatone + \fi + }% + {% + \hangindent1em\noindent##1:\kern.5em + \ifacro\pdfnote##2.\else##2\fi.% + \par + }% + }% + % indexing macros for grammar terms + \def\termidstring##1{% processed name in italics + \numberstocharsandspaces##1\end + \let\optstrextra\optstrextraesc + \expandafter\nameproc\expandafter{\the\toksa}% + \def\idxentry{{\it\the\toksa}}% + }% + \def\termvstring##1{% processed name in typewriter style + \numberstocharsandspaces##1\end + \let\optstrextra\optstrextraesc + \expandafter\nameproc\expandafter{\the\toksa}% + \def\idxentry{{\tt\def\_{\char`\_}\the\toksa}}% + }% + \def\termttstring##1{% straightforward typewriter text + \numberstocharsandspaces##1\end + \def\idxentry{{\tt\the\toksa}}% + }% + \def\termostring##1{% options (e.g. \flex\ and \bison\) + \numberstocharsandspaces##1\end + \def\idxentry{{$\langle$\bf\the\toksa$\rangle$}}% + }% + \let\termhdrstring\termidstring + \def\termstring##1{% + \numberstocharsandspaces##1\end + \let\optstrextra\optstrextraesc + \expandafter\nameproc\expandafter{\the\toksa}% + \def\idxentry{{\tt"\the\toksa"}}% + }% + \def\texcsstring##1{% + \numberstocharsandspaces##1\end + \def\idxentry{% + \def\texnspace{index}% + \def\getcescape{% an \ seen is really an \, and will not go through C string processing + \def\next{escape}% + \action\next\in\currentstate + }% + \termindexfalse\expandafter\inlineTeXx\expandafter{\expandafter/\the\toksa}% + }% + }% + \expandafter\def\csname acharswitch:index\endcsname{% correct reserved \TeX\ characters a la CWEB verbatim + %$\%\\ % unaffected + %\#\ % these never appear + _{% + \yybyte\expandafter{\csname \the\yybyte\endcsname}% + \expandafter\yycp@\expandafter`\the\yybyte\relax + \mkpurebyte + \yyreturn + } + }% + \expandafter\setspecialcharsfrom\csname acharswitch:index\endcsname + \expandafter\let\expandafter\acharswitch\csname acharswitch:index\endcsname + \def\texlexer{% now that all character codes are 12 + \let\default\yygetchar + \let\next\yycp@ + \ifnum\yycp@>"3F % + \ifnum\yycp@<"5B % an uppercase letter or @ + \def\next{letter}% + \fi + \fi + \ifnum\yycp@>"60 % + \ifnum\yycp@<"7B % + \def\next{letter}% + \fi + \fi + \action\next\in\currentstate + }% + \def\indexseparator##1##2{% + \vskip.5\baselineskip + \centerline{\dinkus}% + \vskip.5\baselineskip + } + \def\GI##1##2##3##4.{% + {% + \def\hostparsernamespace{##1}% + \toksa{}##2{##3}% + \I{\idxentry}##4.% + }% + }% + % end indexing macros for grammar terms + \let\*=\lapstar + \def\[##1]{{\it##1}} % definitions + \def\(##1){$\underline{##1}$} % underlined index item + \def\(##1){{\bf ##1}} % an alternative to the above + \def\e##1e{##1{\sevenpoint$^\circ$}} % terms in examples + \def\f##1f{{\it##1\/\kern.2ex}${}^\circ$} % lhs in examples (italic correction does not seem to be enough) + \def\g##1g{$\underline{##1}^\circ$} % definitions in examples + \def\g##1g{{\bf ##1}$^\circ$} % an alternative to the above + \begindoublecols + \readindex + \otherlangindexseparator + \readgindex +} + +\def\otherlangindexseparator{% + \par + \vskip.5\baselineskip + \centerline{B{\sc ISON AND} \TeX\ {\sc INDEX}}% + \vskip.5\baselineskip + \par +} + +\def\finmod{% + \enddoublecols + \closeout\exampletable + \unsetfootnotes + \parfillskip 0pt plus 1fil + \def\grouptitle{NAMES OF THE SECTIONS} + \let\topsecno=\nullsec + \message{Section names:} + \setpage + \def\note##1##2.{\quad{\eightrm##1~\ifacro{\pdfnote##2.}\else{##2}\fi.}} + \def\Q{\note{Cited in section}} % crossref for mention of a section + \def\Qs{\note{Cited in sections}} % crossref for mentions of a section + \def\U{\note{Used in section}} % crossref for use of a section + \def\Us{\note{Used in sections}} % crossref for uses of a section + \def\I{\par\hangindent 2em}\let\*=* + \ifacro + \def\outsecname{Names of the sections} + \let\Xpdf\X + % + \ifpdftex + \makebookmarks + \pdfdest name {NOS} fitb + \pdfoutline goto name {NOS} count -\secno {\outsecname} + \def\X##1:##2\X{\Xpdf##1:##2\X \firstsecno##1.% + {\toksF={}\makeoutlinetoks##2\outlinedone\outlinedone}% + \pdfoutline goto num \the\toksA \expandafter{\the\toksE}} + \else + \ifpdf + \special{pdf: outline -1 << /Title (\outsecname) + /Dest [ @thispage /FitH @ypos ] >>} + \def\X##1:##2\X{\Xpdf##1:##2\X \firstsecno##1.% + {\toksF={}\makeoutlinetoks##2\outlinedone\outlinedone}% + \special{pdf: outline 0 << /Title (\the\toksE) + /A << /S /GoTo /D (\romannumeral\the\toksA) >> >>}} + \fi + \fi + \fi + % + \bigskip + \vskip0pt plus 5pt + \penalty-10 + \tenpoint + \centerline{\sc A LIST OF ALL SECTIONS} + \penalty300 + \medskip + \readsections +} + +\newread\trygindex + +\def\readgindex{% + \openin\trygindex=\jobname.gdy + \ifeof\trygindex + \else + \closein\trygindex + \input \jobname.gdy + \fi +} + +% main section macro + +\let\oldB\B + +% stage one macros for `\B' sections: collecting tokens + +% \B is always paired with \par (see CWEAVE section 213) + +\long\def\Bvbpp#1\par{% + \Bvbp@#1\X\X${}\E{}$\par +} + +\long\def\Bvbp@#1\X#2\X$#3\E#4$#5\par{% + \yystringempty{#5}% + {% + \Bvb@@#1\X#2\X$#3\E#4$\par + }{% + \Bvb@@#1\X#2\X${#3}\E{#4}$\begingroup + \ninepoint + #5\par\endgroup + }% +} + +\long\def\Bvb@@#1\X\X$#2\E#3$\par{% + \oldB#1\par +} + +\def\begingsec#1#2\endgsec{% + \ifmmode + \yybreak{{}${}\vbpp{}$#2\vb\endgsec{#1}{$#2}}%$ + \else + \yybreak{\vbpp{}#2\vb\endgsec{#1}{#2}}% + \yycontinue +} + +\long\def\vbpp#1#2\vb#3#{% verbatim section preprocessor + \yystringempty{#3}{% + \vbp@{#1\stashed{#2}}% + }{% + #3{#1\stashed{#2}}% + }% +} + +\long\def\vbp@#1#2{% + \vbpp{#1#2}% +} + +\let\B\Bvbpp + +% URL typesetting + +\def\url#1{% + \hskip0pt plus .3\hsize\penalty100 + \hskip0pt plus -.3\hsize + {% + \def~{\string~}% + \ifmakepdf + \pdfURL{{\tt #1}}{#1}% + \else + {\tt #1}% + \fi + }% + \hskip0pt plus .2\hsize\penalty100 + \hskip0pt plus -.2\hsize +} + +% commonly used names + +\def\CWEB{\.{CWEB}}\def\CTANGLE{\.{CTANGLE}}\def\CWEAVE{\.{CWEAVE}} +\def\splint{\.{SPLinT}} +\def\POSIX{{\sc POSIX}} +\def\ISO{{\mc ISO}} +\def\bison{\.{bison}} +\def\flex{\.{flex}} +\def\lex{\.{lex}} +\def\gcc{\.{gcc}} +\def\GNU{{\sc GNU}} +% from tugboat.cmn +\newbox\TestBox +\def\La{\tempca=\the\fam \leavevmode L% + \setbox\TestBox=\hbox{$\fam\tempca\scriptstyle A$}% + \kern-.5\wd\TestBox\raise.42ex\box\TestBox} +\def\LaTeX{\La\kern-.15em\TeX} + +\def\sqbullet{\kern.3ex\vrule height .9ex width .8ex depth -.1ex }% square bullet (from manmac.tex) + +\def\sqebullet{% empty square bullet + \kern.3ex\vbox{\hsize=.8ex + \hrule height .4pt + \kern-.4pt + \hbox to\hsize{\vrule height .9ex \hfill\vrule height .9ex} + \kern-.4pt + \hrule height .4pt + \kern.1ex + }% +} + +% debugging + +\def\shownethe#1{% + \edef\next{\the#1}% + \ifx\next\empty + \else + \showthe#1% + \fi +} + +\def\showem#1#2#3{\toksa{#1}\toksb{#2}\toksc{#3}{\newlinechar=`^^J% + \errmessage{% + arg. 1: \the\toksa^^J% + arg. 2: \the\toksb^^J% + arg. 3: \the\toksc% +}}} + +% sugar + +\def\FOREVER{{\bf forever}} + +% delay functions prettyprinting and other miscellanea; + +\def\delayhalfsec{\hbox{wait \kern-.5pt\raise1pt\hbox{$\scriptstyle1$}% +\kern-1pt/\kern-1pt\lower1pt\hbox{$\scriptstyle2$} sec, }} +\def\delayquartersec{\hbox{wait \kern-.5pt\raise1pt\hbox{$\scriptstyle1$}% +\kern-1pt/\kern-1pt\lower1pt\hbox{$\scriptstyle4$} sec, }} + +\def\delay#1sec{% +\hbox{\def\secmult{}wait +\getsecmult#1\end +\if\secmult u\def\secmodifier{ $\mu$\kern.05pt }\else +\if\secmult m\def\secmodifier{ m}\else +\if\secmult n\def\secmodifier{ n}\else + \secmult\def\secmodifier{ }% +\fi\fi\fi +\secmodifier sec$\rm\scriptstyle s$, } +} + +\def\getsecmult#1{% +\ifx#1\end\let\next\relax\else + \secmult\def\secmult{#1}\let\next\getsecmult +\fi\next +} + +% attribute prettyprinting; + +\long\def\parseattrib#1#2\end{\csname attrib#1\endcsname} + +\def\xxattributexx#1{\ifx(#1\let\next\xxattributex\else\let\next\xxattribute\fi\next#1} +\def\xxattributex((\\#1{% + \expandafter\let\expandafter\currentattrib\csname attrib#1\endcsname + \ifx\currentattrib\attribpacked + \strut\colorblack{% + \lower2pt\hbox{\vrule width \wd\thezero height + \ht\thezero depth + \dp\thezero}}\llap{\colorwhite{\hbox{$\scriptscriptstyle\bf 01\kern.5pt$}}}% + \let\next\eatparentheses + \fi + \ifx\currentattrib\attribnoinline + {\ \bf noinline\rm_a}% + \let\next\eatparentheses + \fi + \ifx\currentattrib\attribformat + {\ \bf format\rm_a}% + \let\next\eatarguments + \fi + \next +} + +\def\eatparentheses#1)){} +\def\eatarguments(\\#1,#2,#3))){(\hbox{\rm as }\.{#1})} + +\def\xxattribute#1{\.{\_\_attribute\_\_} (\sc GNU) #1} + +\let\attribnoinline=1 +\let\attribpacked=2 +\let\attribformat=3 + +\tenpoint +%\registerlegend{{8}{\noexpand\phantom{B}}} diff --git a/support/splint/tex/stokenset.sty b/support/splint/tex/stokenset.sty new file mode 100644 index 0000000000..7146fcf0c1 --- /dev/null +++ b/support/splint/tex/stokenset.sty @@ -0,0 +1,23 @@ +% 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/>. + +\prettywordpair{OPTIONAL}{{\tt opt}}% +\prettywordpair{NO_ATTR}{{\tt na}}% +\prettywordpair{EXTENDED}{{\tt ext}}% +\prettywordpair{INTEGER}{{$[\,0\ldots9\,]\ast$}}% +\prettywordpair{IDENTIFIER}{{$[\,\hbox{\tt a}\ldots\hbox{\tt Z}\,0\ldots9\,]\ast$}}% +\prettywordpair{WILDCARD}{{{\tt *} {\rm or} {\tt ?}}}% +\prettywordpair{PERCENT_IDENTIFIER}{{\tt\%$[\,\hbox{\tt a}\ldots\hbox{\tt Z}\,0\ldots9\,]\ast$}}% diff --git a/support/splint/tex/trt1.sty b/support/splint/tex/trt1.sty new file mode 100644 index 0000000000..e3e722c91f --- /dev/null +++ b/support/splint/tex/trt1.sty @@ -0,0 +1,37 @@ +% Copyright 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/>. + +\csname loadtexruntime1\endcsname + +\message{Temporary register definitions ...} +\newcount\tempca +\newcount\tempcb +\newcount\tempcc +\newcount\tempcd +\newcount\tempce + +\newdimen\tempda +\newdimen\tempdb +\newdimen\tempdc + +\newtoks\toksa +\newtoks\toksb +\newtoks\toksc +\newtoks\toksd +\newtoks\tokse +\newtoks\toksf + +\expandafter\def\csname loadtexruntime1\endcsname{\endinput} diff --git a/support/splint/tex/xarithm.sty b/support/splint/tex/xarithm.sty new file mode 100644 index 0000000000..4d424a863c --- /dev/null +++ b/support/splint/tex/xarithm.sty @@ -0,0 +1,317 @@ +% Copyright 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/>. + +% a minimum of expandable arithmetic to implement a few macros in yyparse.sty and flex.sty +% the goal of these macros was not implementing a complete +% integer arithmetic but rather providing the minimal functionality +% where such arithmetic is required. +% there are a few instances in which the utility of such arithmetic is +% beneficial: +% o whenever an `expession macro' should behave like a number (i.e. be +% useful in a \number context); see \YYSTART implementation for an +% example +% o whenever the use of a register is to be avoided in iterative +% macros and replaced by a `tail parameter' (see \yyless for a hint +% of such a use) +% o whenever \TeX's number size limitations are inadequate +% +% the last situation has not been a concern for this package while the +% other two were. +% +% `expandable' may have different meanings. in the context of +% arithmetic, expansion within \edef context, `prefix expansion' or +% \number or \romannumeral0 context expansion may all be valid +% targets. the preferred way seems to be the \romannumeral0 +% interface. the disadvantage of this method is that each macro needs +% to produce a space at the end of its `expansion cycle', the +% advantage is the ability to carry the extension for arbitrarily +% large numbers (unlike, say, the \number interface). the macros below +% are implemented so that the \expandafter\expandafter `prefix' +% expansion and \number both work, even though internally, the +% \romannumeral0 approach is taken. this is done to present a cleaner +% use pattern to the consumer of the macros. +% +% for a complete implementation of expandable arithmetic (including +% floating point), see the corresponding parts of the +% \LaTeX\ project. it was decided against using that implementation to +% avoid creating dependencies. + +% temporary definition, to avoid using reserved counters + +\edef\xxcarry{\count3=\the\count3\count\z@\the\count\z@\count\@ne\the\count\@ne} + +% digit extractor, used as part of several macros below. + +\count\z@\z@ +\bloop + \edef\next{\def\csname digit\number\count\z@\endcsname##1\number\count\z@##2##3.{##2}}\next % +\ifnum9>\count\z@ + \advance\count\z@\@ne +\repeat + +% multiplication tables: +% \xmultby?#1 expands into a pair ab which is a product of ? and #1 + +\count\z@\z@ +\bloop{% + \count\@ne\z@ + \let\next\empty + \bloop + \count3\count\z@ + \multiply\count3\count\@ne + \edef\next{\next\number\count\@ne{\ifnum9<\count3 \else0\fi\number\count3}}% + \ifnum9>\count\@ne + \advance\count\@ne\@ne + \repeat + \edef\next{\def\csname xmultby\number\count\z@\endcsname##1{\noexpand\csname digit##1\noexpand\endcsname\next.}}\next +\ifnum9>\count\z@ + \advance\count\z@\@ne +}\repeat + +% addition tables: +% \xaddto?#1 expands into a pair ab which is a sum of ? and #1 + +\count\z@\z@ +\bloop{% + \count\@ne\z@ + \let\next\empty + \bloop + \count3\count\z@ + \advance\count3\count\@ne + \edef\next{\next\number\count\@ne{\ifnum9<\count3 \else0\fi\number\count3}}% + \ifnum9>\count\@ne + \advance\count\@ne\@ne + \repeat + \edef\next{\def\csname xaddto\number\count\z@\endcsname##1{\noexpand\csname digit##1\noexpand\endcsname\next.}}\next +\ifnum9>\count\z@ + \advance\count\z@\@ne +}\repeat + +% division tables: +% \xdivby?#1 expands into #1 div ? + +\count\z@\@ne +\bloop{% + \count\@ne\z@ + \let\next\empty + \bloop + \count3\count\@ne + \divide\count3\count\z@ + \edef\next{\next\number\count\@ne{\number\count3}}% + \ifnum9>\count\@ne + \advance\count\@ne\@ne + \repeat + \edef\next{\def\csname xdivby\number\count\z@\endcsname##1{\noexpand\csname digit##1\noexpand\endcsname\next.}}\next +\ifnum9>\count\z@ + \advance\count\z@\@ne +}\repeat + +\xxcarry % restore registers + +% #1\times #2 + #3 + +\def\xxcarry#1#2#3{% + \expandafter\x@carry\number1\csname xmultby#1\endcsname#2#3% +} + +% #1 is a bogus parameter, so that a leading 0 is not dropped by \number + +\def\x@carry#1#2#3#4{% + \expandafter\x@@arry\number1\csname xaddto#3\endcsname#4#2% +} + +\def\x@@arry#1#2#3#4{% + \ifnum#2>\z@\number\csname xaddto#2\endcsname#4\else#4\fi#3% +} + +% most macros internally consume the digits from left to right. + +\def\xreverse#1{% + \romannumeral0\xr@verse{}#1.% +} + +\def\xr@verse#1#2{% + \if#2.% + \yybreak{ #1}% + \else + \yybreak{\xr@verse{#2#1}}% + \yycontinue +} + +% multiplication by 0-9 +% #1 is the number +% #2 is the digit +% expands to #1 * #2 in reverse digid order + +\def\xmultiplybydigit#1#2{% + \romannumeral0\xbydigit{#2}{0}{}#1.% +} + +% #1 is the digit +% #2 is the carry +% #3 is the result +% #4 is the next digit of the big factor + +\def\xbydigit#1#2#3#4{% + \if#4.% + \yybreak{\ifnum#2=\z@\xskiptofi{ #3}\else\xskiptofi{ #3#2}\fi}% + \else + \yybreak{\expandafter\xb@digit\number1#1\xxcarry#1#4#2 {#3}}% + \yycontinue +} + +% #1 is a bogus parameter (see above) +% #2 is the digit +% #3 is the carry +% #4 is the next digit of the result +% #5 is the result up to now + +\def\xb@digit#1#2#3#4#5{% + \xbydigit#2#3{#5#4}% +} + +% a version of the macros above that perform the reversion to save an +% extra step + +% #1 is the digit +% #2 is the carry +% #3 is the result +% #4 is the next digit of the big factor + +\def\xbytigid#1#2#3#4{% + \if#4.% + \yybreak{\ifnum#2=\z@\xskiptofi{ #3}\else\xskiptofi{ #2#3}\fi}% + \else + \yybreak{\expandafter\xb@tigid\number1#1\xxcarry#1#4#2 {#3}}% + \yycontinue +} + +% #1 is a bogus parameter (see above) +% #2 is the digit +% #3 is the carry +% #4 is the next digit of the result +% #5 is the result up to now + +\def\xb@tigid#1#2#3#4#5{% + \xbytigid#2#3{#4#5}% +} + +% similar to \xmultiply by digit above by produces the result in the +% usual digit order + +\def\xsmallmultiple#1#2{% + \romannumeral0\expandafter\xsm@llmultiple\expandafter{\romannumeral0\xr@verse{}#1.}#2% +} + +\def\xsm@llmultiple#1#2{% + \xbytigid{#2}{0}{}#1.% +} + +% division by 2 + +\def\xdivbytwo#1{% + \romannumeral0\expandafter\xdivbytw@\romannumeral0\xr@verse{}#1..% +} + +\def\xdivbytw@#1#2{% + \if#2.% + \yybreak{\expandafter\space\number\csname xdivby2\endcsname#1}% + \else + \yybreak{\expandafter\xdivb@tw@\expandafter{\number\csname xdivby2\endcsname#1}#2}% + \yycontinue +} + +\def\xdivb@tw@#1{% + \xbytigid{5}{#1}{}% +} + +% increment by 1 + +\def\xincrement#1{% + \romannumeral0\expandafter\x@ncrement\expandafter{\romannumeral0\xr@verse{}#1.}% +} + +\def\x@ncrement#1{% + \x@ncr@ment{1}{}#1.% +} + +% #1 is the carry +% #2 is the result +% #3 is the next digit of the operand + +\def\x@ncr@ment#1#2#3{% + \if#3.% + \yybreak{\ifnum#1=\z@\xskiptofi{ #2}\else\xskiptofi{ #1#2}\fi}% + \else + \yybreak{\ifnum#1=\z@\xskiptofi{\x@@cr@m@nt{#3#2}}\else + \xskiptofi{\expandafter\x@ncr@m@nt\number1\csname xaddto#1\endcsname#3{#2}}\fi}% + \yycontinue +} + +\def\x@ncr@m@nt#1#2#3#4{% + \x@ncr@ment#2{#3#4}% +} + +\def\x@@cr@m@nt#1#2.{% + \xr@verse{}#2.#1% +} + +% decimal complements table + +\def\xcplof#1{\ifcase#1 \or9\or8\or7\or6\or5\or4\or3\or2\or1\fi} + +% single digit decrement by 1 table + +\def\xdecof#1{\ifcase#1 \or0\or1\or2\or3\or4\or5\or6\or7\or8\fi} + +% decrement by 1 + +\def\xdecrement#1{% + \romannumeral0\expandafter\xd@crement\expandafter{\romannumeral0\xr@verse{}#1.}% +} + +\def\xd@crement#1{% + \xd@cr@ment1{}#1.% +} + +% #1 is the carry +% #2 is the result +% #3 is the next digit of the operand + +\def\xd@cr@ment#1#2#3{% + \if#3.% + \yybreak{ -1}% + \else + \yybreak{\ifnum#1=\z@ + \xskiptofi{\xde@@@m@nt{#3#2}}% + \else + \xskiptofi{% + \ifnum#3=\z@ + \xskiptofi{\xd@cr@ment1{9#2}}% + \else + \xskiptofi{\expandafter\xde@@@m@nt\expandafter{\number\xdecof#3 #2}}% + \fi}% + \fi}% + \yycontinue +} + +\def\xd@cr@m@nt#1#2#3{% + \xd@cr@ment#1{#2#3}% +} + +\def\xde@@@m@nt#1#2.{% + \xr@verse{}#2.#1% +} diff --git a/support/splint/tex/yxunion.sty b/support/splint/tex/yxunion.sty new file mode 100644 index 0000000000..fb0d2460b3 --- /dev/null +++ b/support/splint/tex/yxunion.sty @@ -0,0 +1,33 @@ +% Copyright 2012-2015, 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/>. + +% the original, minimal bootstrapping macros were designed to process +% \prodstyle{\%token} declarations only and are enough to establish the +% interface between the \bison\ parser and the \bison\ lexer; to serve +% the secondary task of providing typesetting information to +% the \bison\ parser, all forms of token declarations must be processed. + +\restorecslist{bootstrap}\yyunion % get the original bootstrap macros + +\def\precdecls#1#2#3#4#5{#3} + +\def\symbolprec#1#2{% + \toksa{}\toksb{}% + #1% + \yytoksempty\toksb{}{\immediate\write\tokendefs{\noexpand\tokenpp{\the\toksb}}}% +} + +\savecslist{bootstrap}\yyunion diff --git a/support/splint/tex/yy.sty b/support/splint/tex/yy.sty new file mode 100644 index 0000000000..22a7948e9d --- /dev/null +++ b/support/splint/tex/yy.sty @@ -0,0 +1,76 @@ +% 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/>. + +% macros for typeseting productions + +% these macros carefully orchestrate the startup of the parsing machinery, bootstrapping the parser if +% necessary. they can be used as an example of such macros when different use of the parsing mechanisms +% is desired. + +\ifx\optimization\UNDEFINED % this trick is based on the premise that \UNDEFINED is never defined nor + \def\optimization{0}% created with \csname ... \endcsname +\fi + +\newwrite\tokendefs +\let\nx\noexpand + +\def\drvname{bo} + +\input yycommon.sty % general routines for stack and array access +\input yymisc.sty % helper macros (stack manipulation, table processing, value stack pointers) +\input yyinput.sty % input functions +\input yyparse.sty % parser machinery +\input flex.sty % lexer functions +\input yyboth.sty % parser intitialization, optimization + +\ifnum\optimization>\tw@ + \input yyfaststack.sty +\fi + +\input yystype.sty % scanner auxilary types and functions +\input yyunion.sty % parser data structures + +\def\indexpseudonamespace{[index]} + +% the main parser + +\let\parsernamespace\empty + +\def\modebootstrap{% + \edef\tokendeffile{\drvname.tok}% + \edef\bstrapparser{byytab.tex}% sets \bootstrapmodetrue + \def\bootstraplexersetup{\let\yylexreturn\yylexreturnbootstrap}% only return tokens whose value is known at bootstrap + \input yybootstrap.sty% +} + +\def\modenormal{% + \def\appendr##1##2{% faster but dirtier + \edef\appnext{##1{\the##1##2}}\appnext + }% + \def\appendl##1##2{% faster but dirtier + \edef\appnext{##1{##2\the##1}}\appnext + }% + %\def\fgetelemof##1\at##2{% speeds up the lookup + % \csname ##1\parsernamespace\the##2\endcsname + %}% + \input yyinit.sty% +} + +\ifx\modeactive\UNDEFINED + \def\modeactive{\modenormal} +\fi + +\modeactive diff --git a/support/splint/tex/yybootstrap.sty b/support/splint/tex/yybootstrap.sty new file mode 100644 index 0000000000..185ad3b0a6 --- /dev/null +++ b/support/splint/tex/yybootstrap.sty @@ -0,0 +1,70 @@ +% 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/>. + +% token equivalence table does not exist, switch to a bootstrap parser + +\ifx\tokendeffile\UNDEFINED +\else + \immediate\openout\tokendefs=\tokendeffile +\fi +\genericparser + name: main, + ptables: \bstrapparser, + ltables: cweb/ltab.tex, + tokens: {}, + asetup: \bootstraplexersetup, + dsetup: \newlexerstateextra, + rsetup: \noexpand\savefullstateextra, + optimization: \optimizeall;% + +\tomainparser % this saves the current state + +\input yytexlex.sty + +\let\unparse\eatone + +\expandafter\def\csname parserstack[b]\endcsname#1#2{% + \parsevb{#1}% Stage two, start the parsing + \ifyyparsefail % do nothing if parsing failed + \yybreak{}% + \else % Stage three, process the parsed table + \yybreak{\initbootstrap\the\table}% + \yycontinue +} + +\expandafter\def\csname parserstack[]\endcsname#1#2{% + \parsevb{#1}% Stage two, start the parsing + \ifyyparsefail % do nothing if parsing failed + \yybreak{}% + \else % Stage three, process the parsed table + \yybreak{\initbootstrap\the\table}% + \yycontinue +} + +% stage two macros: parsing + +\def\parsevb#1{% + %\ifchecktable {\toks0{#1}\errmessage{table before parsing: \the\toks0}}\fi + \tomainparser % this is not currently required since there are no namespace switching macros + % in the \TeX\ portion of the text; it is left here in case such macros are used in the future + \doparse{#1}% +} + +\long\def\beginprod#1\endprod{% + \endgroup +} + +\let\begincprod\beginprod diff --git a/support/splint/tex/yyboth.sty b/support/splint/tex/yyboth.sty new file mode 100644 index 0000000000..f15fe006c2 --- /dev/null +++ b/support/splint/tex/yyboth.sty @@ -0,0 +1,181 @@ +% 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/>. + +% parser environment + +\newif\ifyyskipparse +\newif\ifsaveparseoutput +\newif\ifchecktable +\newif\ifchecktrim + +\newwrite\exampletable + +\def\basicparserinit{% + \yytext{}% + \yytextpure{}% + \yytextseenpure{}% + \yytextseen{}% + \yybyte{}% + \yyfbyte{}\yysbyte{}% + \yystash{}% + \yystashseen{}% + \yyformat{}% + \yyformatseen{}% + \yyfutureyytext{}% + \yyinitstack\yystatestack + \yyfmark=\z@ + \yysmark=\z@ + \yyfmarklast=\z@ + \formatmarker=\z@ + \yysmarklast=\z@ + \stashmarker=\z@ + \yytextbackupfalse + \yyg@yyinit=\z@ + \yyg@yystart=\z@ + \YYATBOL=\@ne + \yyparsefailfalse + \YYEOBLASTMATCHtrue +} + +\def\parserinit{% + \basicparserinit + \yyinitstack\obstackforstring + \yyinitstack\obstackforstringraw + \percentpercentcount=\z@ + \lonesting=\z@ + \laststring{}\laststringraw{}% + \currentlaststring{}\currentlaststringraw{}% + \parserdatainit +} + +\def\parserdatainit{% + % make control sequences inserted by the parser non expandable to facilitate + % token list manipulation; currently nothing is done +} + +% optimization options + +\def\optimizeall{% + % lexer + \ifnum\optimization>\z@ + \optimize{yynxt}% + \optimize{yyaccept}% + \optimize{yydef}% + \optimize{yychk}% + \optimize{yybase}% + \optimize{yyec}% + \optimize{yymeta}% + \tracingstats=\@ne + \fi + % parser + \ifnum\optimization>\@ne + \optimize{yytranslate}% + \optimize{yyrone}% + \optimize{yyrtwo}% + \optimize{yyrthree}% + \optimize{yydefact}% + \optimize{yydefgoto}% + \optimize{yypact}% + \optimize{yypgoto}% + \optimize{yytable}% + \optimize{yycheck}% + \optimize{yyprhs}% + \optimize{yyrhs}% + \optimize{yytoknum}% + \optimize{yystos}% + \optimizetext{yytname}% + \fi +} + +\long\def\endgsec#1#2#3{% + \ifyyskipparse + \yybreak{\unparse{#3}}% + \else + \yybreak{\csname parserstack[#2]\endcsname{#1}{#3}}% + \yycontinue +} + +\let\endcprod\endgroup +\let\endmprod\endgroup +\let\endprod\endgroup + +\def\genericparser name: #1, ptables: #2, ltables: #3, tokens: #4, asetup: #5, dsetup: #6, rsetup: #7, optimization: #8;{% + % parser initialization + % + \expandafter\def\csname #1namespace\endcsname{[#1]}% + \savecs{local-namespace}\parsernamespace + \expandafter\let\expandafter\parsernamespace\csname #1namespace\endcsname + \pinittoks{}% + \input #2 % load main parser table + \settokens % set the values of all tokens + \yystringempty{#4}{}{% + \input #4 % use token equivalence table to set the values of non-string tokens + }% + #5% additional setups + % + \input #3 % load lexer tables + % + % at this point the macros inside the table files (\newtable, \constset, + % \yybigswitch, \stashswitch, \addname, \yydoactionswitch, \setflexstates, + % \stateset, \tokeneq) have set up the corresponding stuctures in + % the `parser namespace' (e.g. if the parser namespace is `main', + % \newtable{yyaccept} created a token register \yyaccept[main]), + % assigned the `generic' names to them (to continue + % the example above, \newtable does \let\yyaccept\yyaccept[main]) and + % recorded the corresponding commands in \pinittoks for future use. + % + % lexer state macros are namespace specific (just like token names) + % so they have to be set in each namespace. + % + \setflexstates + #8% possible optimization + % + % finally, we add the definitions for the variables used in running + % the lexer and the parser. + \newparserstate + \newlexerstate + #6% additional data setup (say, \newlexerstateextra) + % + % we record all the commands necessary to switch to the desired namespace + % in a convenient macro + \expandafter\edef\csname to#1parser\endcsname{% + \noexpand\savefullstate % save the state of the current parser + #7% any data that needs to be saved + % switch to the new namespace + \let\noexpand\parsernamespace\expandafter\noexpand\csname #1namespace\endcsname + \the\pinittoks % restore all the tables, tokens and constants, and stacks + \let\noexpand\getcurrentparser\expandafter\noexpand\csname to#1parser\endcsname + }% + \restorecs{local-namespace}\parsernamespace +} + +\def\genericprettytokens namespace: #1, tokens: #2, correction: #3, host: #4;{% + \savecs{local-namespace}{\parsernamespace\tokeneq}% + \yystringempty{#2}{}{% + \expandafter\let\expandafter\parsernamespace\csname #1namespace\endcsname + \def\tokeneq##1##2{\prettytoken{##1}}% + \let\tokenpp\prettytoken + \input #2 % /* re-use token equivalence table to set the typesetting of tokens */ + }% + \yystringempty{#3}{}{% + \expandafter\let\expandafter\parsernamespace\csname #1namespace\endcsname + \input #3 % input customized typesetting rules for tokens + }% + \yystringempty{#4}{}{% + \expandafter\let\expandafter\hostparsernamespace\csname #4namespace\endcsname + }% + \restorecs{local-namespace}{\parsernamespace\tokeneq}% +} 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 diff --git a/support/splint/tex/yyfaststack.sty b/support/splint/tex/yyfaststack.sty new file mode 100644 index 0000000000..cc43c33115 --- /dev/null +++ b/support/splint/tex/yyfaststack.sty @@ -0,0 +1,352 @@ +% 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/>. + +% fast versions of stack access functions + +\catcode`\@=11 + +\def\yyinitstack#1{% #1 is the counter + \csname \expandafter\eatone\string#1<count>\endcsname\m@ne +} + +% stacks will be defined as pairs ( \s t a c k n a m e [n u m b e r], \s t a c k n a m e <count> ) +% where \s t a c k n a m e [n u m b e r] is a control sequence and \s t a c k n a m e <count> +% is a \count register +% +% note that in the implementaion below the stack grows `the wrong +% way'; this is done for convenience, since there is no `memory read +% with increment' operation, the `usual' (say, hardware) stack +% implementations take advantage of, and our stack can grow +% unrestricted this way + +\def\getstackpointer#1{% expands to the value of the current top of the stack position + \expandafter\the\csname \expandafter\eatone\string#1<count>\endcsname +} + +\def\gettopofstackcs#1{% expands to the control sequence (a member of the associative array) + % that holds the value of the current element at the top of the stack + \csname \expandafter\eatone\string#1[\getstackpointer#1]\parsernamespace\endcsname +} + +\def\getmidstackcs#1#2{% expands to the control sequence (a member of the associative array) + % that holds the value of the current element at the specified (#2) position + \csname \expandafter\eatone\string#1[#2]\parsernamespace\endcsname +} + +\def\movestackpointer#1\by#2{% + \expandafter\advance\csname \expandafter\eatone\string#1<count>\endcsname#2% +} + +\def\yypopstack#1\by#2{% removes the top #2 elements from the top of the stack #1 + \movestackpointer#1\by{-#2}\relax +} + +% + +\def\yypop#1\into#2{% + #2\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter{\gettopofstackcs#1}% + \movestackpointer#1\by\m@ne +} + +% 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{% + \movestackpointer#2\by\@ne + \expandafter\expandafter\expandafter\def\gettopofstackcs#2{#1}% +} + +% push register contents on a stack: #1 is a register, #2 is a stack + +\def\yypushr#1\on#2{% + \movestackpointer#2\by\@ne + \expandafter\expandafter\expandafter\edef\gettopofstackcs#2{\the#1}% +} + +% 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{% + \expandafter\advance\csname \expandafter\eatone\string#1<count>\endcsname-#2\relax + % + \expandafter\let\expandafter#3\csname \expandafter\eatone\string#1[\expandafter\the + \csname \expandafter\eatone\string#1<count>\endcsname]\parsernamespace\endcsname + % + \expandafter\advance\csname \expandafter\eatone\string#1<count>\endcsname#2\relax +} + +% same as above but reads the value into a register + +\def\yyreadstackr#1\at#2\to#3{% + \expandafter\advance\csname \expandafter\eatone\string#1<count>\endcsname-#2\relax + % + #3\csname \expandafter\eatone\string#1[\expandafter\the + \csname \expandafter\eatone\string#1<count>\endcsname]\parsernamespace\endcsname\relax + % + \expandafter\advance\csname \expandafter\eatone\string#1<count>\endcsname#2\relax +} + +% the macros below use general purpose registers and have a chance to interfere with +% the user namespace; they have been replaced by the macros that only use expandable +% arithmetic which leads to about 3 percent slowdown. thus the original macros were left +% in the package in case such a slowdown is undesirable + +\def\yyreadvstack#1\upto#2{% assume that #2 > 0 + \tempca=#2\relax + \tempcb\toptoks + \advance\tempcb\@ne + \yyreadvst@ck{#1}% +} + +\def\yyreadvst@ck#1{% + \expandafter\toksdef\csname$$'\the\tempca\endcsname=\tempcb% + \expandafter\yypop\expandafter#1\expandafter\into\csname$$'\the\tempca\endcsname%$ + \expandafter\expandafter\expandafter\def + \expandafter\expandafter\csname$'\the\tempca\endcsname\expandafter{\the\toks\tempcb}%$ + \ifnum\tempca=\@ne %we have read the values + \yybreak\relax + \else + \advance\tempcb\@ne + \advance\tempca\m@ne + \yybreak{\yyreadvst@ck{#1}}% + \yycontinue +} + +% the macros below replace the two macros above to only use expandable arithmetic + +\def\yyreadvstack#1\upto#2{% assume that #2 > 0 + \expandafter\yyr@@dvst@ck\expandafter{\number#2}{#1}% +} + +\def\yyr@@dvst@ck#1#2{% + \expandafter\yyr@@@vst@@k\expandafter{\number\toptoks}{#1}{#2}% +} + +\def\yyr@@@vst@@k#1#2#3{% + \yyr@@dvst@@k{#2}{#1}{#3}% +} + +\def\yyreadvst@ck#1#2#3{% + \expandafter\toksdef\csname$$'#2\endcsname=#1\relax % + \expandafter\yypop\expandafter#3\expandafter\into\csname$$'#2\endcsname%$ + % the portion below is redundant if the \yn macro below is used and no symbolic switch + % is implemented + \expandafter\expandafter\expandafter\def + \expandafter\expandafter\csname$'#2\endcsname\expandafter{\the\toks#1}%$ + \ifnum#2=\@ne %we have read the values + \yybreak\relax + \else + \yybreak{\expandafter\yyr@@dvst@@k\expandafter{\number\xdecrement{#2}}{#1}{#3}}% + \yycontinue +} + +\def\yyr@@dvst@@k#1#2#3{% + \expandafter\yyreadvst@ck\expandafter{\number\xincrement{#2}}{#1}{#3}% +} + +% end of replacement macros + +\def\yypeekvstack#1\upto#2{% assume that #2 > 0 + \yyreadvstack#1\upto{#2}\relax + \movestackpointer#1\by#2\relax +} + +% macros for reading the state stack (needed if using bison version 3.0 and above) + +\def\yyreadsstack#1\upto#2\withprefix#3{% assume that #2 > 0 + \expandafter\yyr@@dsst@ck\expandafter{\number#2}{#1}{#3}% +} + +\def\yyr@@dsst@ck#1#2#3{% + \expandafter\yyr@@@sst@@k\expandafter{\number\toptoks}{#1}{#2}{#3}% +} + +\def\yyr@@@sst@@k#1#2#3#4{% + \yyr@@dsst@@k{#2}{#1}{#3}{#4}{}% +} + +\def\yyr@@dsst@@k#1#2#3#4#5{% + \expandafter\yyreadsst@ck\expandafter{\number\xincrement{#2}}{#1}{#3}{#4}{#5}% +} + +\def\yyreadsst@ck#1#2#3#4#5{% + \ifnum#2=\z@ %we have read the values + \yybreak{#5}% + \else + \yybreak{\expandafter\yyr@@dsst@@@\expandafter{\number\gettopofstackcs#3}{#1}{#2}{#3}{#4}{#5}}% + \yycontinue +} + +\def\yyr@@dsst@@@#1#2#3#4#5#6{% + \movestackpointer#4\by\m@ne + \expandafter\yyr@@dsst@@k\expandafter{\number\xdecrement{#3}}{#2}{#4}{#5}{#5{#1}#6}% +} + +\def\yypeeksstack#1\upto#2\withprefix#3{% assume that #2 > 0 + \yyreadsstack#1\upto{#2}\withprefix{#3}\relax + \movestackpointer#1\by#2\relax +} + +% new stack access macros that read the stack directly (to reduce namespace pollution) +% these are here more as an example + +\def\yn#1#{% + \ifnum#1<\@ne + \yybreak{\putyyval}% + \else + \yybreak{\p@tyyassignment{#1}}% + \yycontinue +} + +\def\p@tyyassignment#1{% + \expandafter\advance\csname yyvsa<count>\endcsname-\yylen + \expandafter\advance\csname yyvsa<count>\endcsname#1\relax + % + \expandafter\expandafter\expandafter + \p@@yyassignment + \expandafter\expandafter\expandafter{% + \csname yyvsa[\expandafter\the + \csname yyvsa<count>\endcsname]\parsernamespace\endcsname + }{% + \expandafter\advance\csname yyvsa<count>\endcsname-#1\relax + \expandafter\advance\csname yyvsa<count>\endcsname\yylen + }% +} + +% \bb macro implementation + +\def\p@twwassignment#1{% + \expandafter\advance\csname yyvsa<count>\endcsname-#1\relax + \expandafter\advance\csname yyvsa<count>\endcsname\@ne + % + \expandafter\expandafter\expandafter + \p@@yyassignment + \expandafter\expandafter\expandafter{% + \csname yyvsa[\expandafter\the + \csname yyvsa<count>\endcsname]\parsernamespace\endcsname + }{% + \expandafter\advance\csname yyvsa<count>\endcsname#1\relax + \expandafter\advance\csname yyvsa<count>\endcsname\m@ne + }% +} + +\def\p@@yyassignment#1#2#3{% + #2\yystringempty{#3}{#1}{#3{#1}}% +} + +\def\putyyval#1{\edef\next{\yyval{#1}}\next} + +% dysplaying stack contents (\yyparse specific) + +\def\showstack#1{% + \begingroup + \let\stackcs\empty + \count\z@\csname \expandafter\eatone\string#1<count>\endcsname + \ifnum\count\z@<\z@ + \else + \bloop + \count\@ne\csname \expandafter\eatone\string#1[\the\count\z@]\parsernamespace\endcsname + \count\tw@=\fgetelemof{yystos}\at{\count\@ne}% + \edef\stackcs{\stackcs^^J \space\space\fgetelemof{yytname}\at{\count\tw@}}% + \ifnum\count\z@>\z@ + \advance\count\z@\m@ne + \repeat + \fi + \tokreturn{}{}{\def\noexpand\stackcs{\stackcs}}% +} + +% saving token registers + +\def\newtable@generic#1{% + \expandafter\ifx\csname #1\endcsname\relax + \toksa{\csname newtoks\endcsname}% + \expandafter\the\expandafter\toksa\csname #1\endcsname + \fi + \csname #1\endcsname=% +} + +\let\newtable\newtable@generic % TODO: right now this is done either for all tables or none of them + +% macros to support `hardwired' optimized tables + +\def\appendtoyy@generic#1{% + \toksa{\or}% + \expandafter\ifx\csname optopt[#1]\parsernamespace\endcsname\relax + \expandafter\concat\csname#1\endcsname\toksb + \expandafter\concat\csname#1\endcsname\toksa + \else + \expandafter\edef\csname #1\parsernamespace\the\tempca\endcsname{\the\toksb}% + \fi +} + +\def\appendtoyy@genericlast#1{% + \expandafter\ifx\csname optopt[#1]\parsernamespace\endcsname\relax + \expandafter\concat\csname#1\endcsname\toksb + \else + \expandafter\edef\csname #1\parsernamespace\the\tempca\endcsname{\the\toksb}% + \fi +} + +\def\beginoptimizednonnumeric#1{% + \tempca\z@ + \def\appendtoyytname{\appendtoyy@generic{#1}}% + \def\appendtoyytnamelast{\appendtoyy@genericlast{#1}}% +} + +% list macros + +\def\listx#1{% #1 is the list name + \expandafter\ifx\csname #1[\the\csname#1<count>\endcsname]\endcsname\relax + \csname#1<count>\endcsname\z@ + \yybreak\relax + \else + \yybreak{\csname #1[\the\csname#1<count>\endcsname]\endcsname + \expandafter\advance\csname#1<count>\endcsname\@ne + \listx{#1}}% + \yycontinue +} + +\def\newlist#1{% + \toksa{\csname newcount\endcsname}% + \expandafter\the\expandafter\toksa\csname#1<count>\endcsname +} + +\def\initlistx#1{% + \csname#1<count>\endcsname\z@ + \expandafter\let\csname #10\endcsname\relax +} + +\def\resetlistx#1{% + \csname#1<count>\endcsname\z@ +} + +\def\listxlastindex#1{% + \the\csname#1<count>\endcsname +} + +\def\addtolist#1#2{% + \expandafter\def\csname#1[\the\csname#1<count>\endcsname]\endcsname{#2}% + \expandafter\advance\csname#1<count>\endcsname\@ne +} + +\def\addxtolist#1#2{% + \expandafter\edef\csname#1[\the\csname#1<count>\endcsname]\endcsname{#2}% + \expandafter\advance\csname#1<count>\endcsname\@ne +} + +\def\finishlist#1{% + \expandafter\advance\csname#1<count>\endcsname\@ne + \expandafter\let\csname#1[\the\csname#1<count>\endcsname]\endcsname\relax +} diff --git a/support/splint/tex/yyinit.sty b/support/splint/tex/yyinit.sty new file mode 100644 index 0000000000..8d9b7d33c3 --- /dev/null +++ b/support/splint/tex/yyinit.sty @@ -0,0 +1,682 @@ +% 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/>. + +% finish parser initialization + +\let\yylexreturn\yylexreturnregular + +\genericparser + name: main, + ptables: cweb/gyytab.tex, + ltables: cweb/ltab.tex, + tokens: \drvname.tok, + asetup: {}, + dsetup: \newlexerstateextra, + rsetup: \noexpand\savefullstateextra, + optimization: \optimizeall;% + +% prologue parser + +\genericparser + name: prologue, + ptables: cweb/dyytab.tex, + ltables: cweb/ltab.tex, + tokens: \drvname.tok, + asetup: {}, + dsetup: \newlexerstateextra, + rsetup: \noexpand\savefullstateextra, + optimization: \optimizeall;% + +% parser for term names: this is not really a great idea in itself but rather an +% illustration of what is possible + +\genericparser + name: small, + ptables: cweb/small_tab.tex, + ltables: cweb/small_dfa.tex, + tokens: {}, + asetup: {}, + dsetup: {}, + rsetup: \noexpand\savefullstateextra, + optimization: \optimizeall;% + +\tomainparser + +\input yytexlex.sty + +\let\unparse\yyid + +\expandafter\def\csname parserstack[b]\endcsname#1#2{% + \parsevb{#1}% Stage two, start the parsing + \ifyyparsefail % revert to generic macros if parsing failed + \yybreak{\message{parsing failed ...}#2}% + \else % Stage three, process the parsed table + \yybreak{\typesetalltables}% + \yycontinue +} + +\expandafter\def\csname parserstack[]\endcsname#1#2{% + \parsevb{#1}% Stage two, start the parsing + \ifyyparsefail % revert to generic macros if parsing failed + \yybreak{\message{parsing failed ...}#2}% + \else % Stage three, process the parsed table + \yybreak{\typesetalltables}% + \yycontinue +} + +% stage two macros: parsing + +\newtoks\symstream + +\def\parsevb#1{% + \ifchecktable + \ifsaveparseoutput + {\toks0{#1}\newlinechar=`^^J\immediate\write\exampletable{^^J\harmlesscomment + table before parsing:^^J\the\toks0}}% + \else + {\toks0{#1}\errmessage{table before parsing: \the\toks0}}% + \fi + \fi + \tomainparser + \doparse{#1}% + \ifyyparsefail + \toprologueparser + \doparse{#1}% + \ifyyparsefail + \else + \ifsaveparseoutput{\newlinechar=`^^J\immediate\write\exampletable{^^J\harmlesscomment parsed table (prologue): + ^^J\the\table}}% + \fi + \fi + \else + \ifsaveparseoutput{\newlinechar=`^^J\immediate\write\exampletable{^^J\harmlesscomment parsed table (grammar): + ^^J\the\table}}% + \fi + \fi +} + +% stage three macros: typesetting + +\def\tlskip{\z@} +\def\tfskip{\parindent} + +\def\typesetalltables{% + \begingroup + \ifchecktable + \ifsaveparseoutput + {\newlinechar=`^^J\immediate\write\exampletable{^^J\harmlesscomment + stashed stream:^^J\the\yystash}}% + \else + \errmessage{parsed table: \the\table^^J^^Jstashed stream: \the\yystash}% + \fi + \fi + \symstream\table + \table{}% + \setprodtable + \the\symstream\relax + \postoks{}\pushothertables + \ifchecktable + \ifsaveparseoutput + \else + \errmessage{table after processing: \the\table}% + \fi + \fi + \ifsaveparseoutput + {\newlinechar=`^^J\immediate\write\exampletable{^^J\harmlesscomment + processed table:^^J\the\table}}% + \fi + \parindent1em + \checkforpropertable\table + \tabskip\tfskip + \ruletableset + \ifchecktable + \message{remaining stash: \the\yystash}% + \fi + \toksa{}\the\yystash + \cleanstash\stripstash\checkforccode + \ifchecktable + \message{stash after cleaning: \the\toksa}% + \fi + \ifnum\wd0>\z@ + %\ifchecktable + % \showboxdepth=1000 + % \showboxbreadth=1000 + % \showbox0 + %\fi + % currently testing for nontrivial leftover stash involves packaging the stash material + % into a \vbox; as a result, the stash containing ${}{}$\hbox{} will have a nonzero length + % which is why the test below is necessary + \ifnum\ht0>\z@ + \indent\boxstash + \fi + \fi + \endgroup +} + +% setting the rule table: cross-section alignment and other effects are applied here; +% in order to produce the proper line skips before and after \unvbox, the rules followed by +% \TeX\ while adding an \halign to a vertical list have to be reproduced explicitly + +\def\ruletableset{% + \par + \vskip-\baselineskip + \ifx\gatoks\relax + \else + \table\expandafter{\the\table\gatoks}% + \fi + \setbox0\vbox\expandafter{\expandafter + \null\expandafter\prevdepth\the\prevdepth + \halign \ifpropertable to \hsize \fi + {\hbox to 2em{##\/$\,${\rm:}\hss}\hfil\tabskip\z@&\setallterms{##}&##\hfil\tabskip0pt plus1fil&% + \toksa{}##\makestashbox\hfil\tabskip\tlskip\cr + \the\table + } + \expandafter + }\expandafter + \unvbox\expandafter0\expandafter + \prevdepth\the\prevdepth\relax +} + +\def\setallterms#1{\setbox\z@=\hbox{\it#1}\ifsquashterms\hbox to0pt{\unhbox\z@\hss}\else\unhbox\z@\fi\hfil} + +% quick and dirty global alignment: the size of the last box (and those in between) +% can be chosen automatically after one pass and read in for the final pass; +% in the future this will be the default implementation; for now, the inelegant +% solution below works as well. + +\def\setglobalalignrules#1{% + \def\gatoks{% + \omit\hfil&\omit\hfil&\omit\hfil&\omit\hfil\hbox to #1{\hfil}\cr + \noalign{\vskip-\baselineskip}% + %\noalign{\centerline{$\diamond$}} + }% +} + +\setglobalalignrules{3 in}% + +% to align all the actions across the document, comment out the next line + +\let\gatoks\relax + +\def\checkforccode{% + \setbox0=\vbox{\setlazyc\the\toksa}% +} + +\def\setlazyc{% + \hidecs{\1\4\5\6\8}% +} + +\newif\ifdisplaytokenraw + +\def\toksdefline#1#2#3#4#5{% #1 is the parsed version of the internal bison name + % #2 is the index entry + % #3 is the type + % #4 is the explicit value + % #5 is the parsed version of the string value + \ifnum\tempca=\z@ + \tokdectoks\expandafter{\the\tokdectoks&{#2}#1\hfil\cr}% + \tempca\tempcb + \else + \ifnum\tempcb=\tempca + \tokdectoks\expandafter{\the\tokdectoks{#2}#1\hfil}% + \else + \tokdectoks\expandafter{\the\tokdectoks&{#2}#1\hfil}% + \fi + \advance\tempca\m@ne + \fi +} + +\def\attachtokentable{% typesetting the token declarations as part of the grammar + \tempcb3 \tempca\tempcb + \expandafter\tokdectoks\expandafter{\expandafter}\the\tokdectoks + \ifnum\tempca=\tempcb + \else + \bloop + \tokdectoks\expandafter{\the\tokdectoks&\omit\hfil}% + \ifnum\tempca=\z@ + \else + \advance\tempca\m@ne + \repeat + \tokdectoks\expandafter{\the\tokdectoks\cr}% + \fi + \toksa{\tt\strut##\hfil\tabskip=0pt plus 1fil}% + \bloop + \toksa\expandafter{\the\toksa&\tt\strut##\hfil}% + \ifnum\tempcb=\tw@ + \else + \advance\tempcb\m@ne + \repeat + \toksa\expandafter{\the\toksa&\tt\strut##\hfil\tabskip\z@\cr}% + \concat\toksa\tokdectoks + \tokdectoks\toksa + \edef\next{\table{\the\table\noalign{% + \tabskip\parindent + \nx\displaytokenrawtrue + \halign to\hsize{\the\tokdectoks}% + }% + }}\next + \tokdectoks{}% +} + +% typesetting token lists, precedence declaratins, etc +% these belong to yyunion.sty but they use `global' settings that are +% too specific to put there + +\def\attachtypestable{% typesetting the type declarations as part of the grammar + \toksa{}\the\typestable + \edef\next{\table{\the\table\noalign{% + {% + \the\toksa + }% + }% + }}\next\typestable{}% +} + +\long\def\onetype#1#2{% + \toksb{{% + \hbadness\@M + \rightskip=\z@ + \tempda\hsize \advance\tempda-1in + \indent{$\langle$\tt union$\rangle.#1$:}\ \hfill\nobreak\hfill\nobreak\null\penalty1\relax\null\nobreak\hfill + \hbox to\tempda{$\vtop{\noindent\hsize\tempda\raggedright #2\strut}$}\par + }}% + \concat\toksa\toksb +} + +\long\def\flexsstatelist#1{% + \toksb{{% + \hbadness\@M + \rightskip=\z@ + \tempda\hsize \advance\tempda-1in + \indent{$\langle$\tt states-s$\rangle_{\rm f}$:}\ \hfill\nobreak\hfill\nobreak\null\penalty1\relax\null\nobreak\hfill + \hbox to\tempda{$\vtop{\noindent\hsize\tempda\raggedright #1\strut}$}\par + }}% + \concat\toksa\toksb +} + +\long\def\flexxstatelist#1{% + \toksb{{% + \hbadness\@M + \rightskip=\z@ + \tempda\hsize \advance\tempda-1in + \indent{$\langle$\tt states-x$\rangle_{\rm f}$:}\ \hfill\nobreak\hfill\nobreak\null\penalty1\relax\null\nobreak\hfill + \hbox to\tempda{$\vtop{\noindent\hsize\tempda\raggedright #1\strut}$}\par + }}% + \concat\toksa\toksb +} + +\def\attachprectable{% typesetting the precedence declarations as part of the grammar + \toksa{}\the\prectable + \edef\next{\table{\the\table\noalign{% + {% + \the\toksa + }% + }% + }}\next\prectable{}% +} + +\long\def\oneprec#1#2#3{% + \toksc{% + \hbadness\@M + \rightskip=\z@ + \tempda\hsize \advance\tempda-1in + \indent + }% + \toksd{% + \ \hfill\nobreak\hfill\nobreak\null\penalty1\relax\null\nobreak\hfill + \hbox to\tempda{$\vtop{\noindent\hsize\tempda\raggedright #3\strut}$}\par + } + \def\next{#2}% + \ifx\next\empty + \toksb{}% + \else + \toksb{${}:{}$#2}% + \fi + \edef\next{\toksb{{$\nx\langle$\nx\bf #1\the\toksb$\nx\rangle$}}}\next + \appendr\toksa{{\the\toksc\the\toksb\the\toksd}}% +} + +\def\attachoptionstable{% typesetting the options as part of the grammar + \edef\next{\table{\the\table\noalign{% + \tabskip\parindent + \halign{####\nx\hfil\tabskip\z@&\nx\qquad\nx\it####\nx\hfil\cr + \the\opttable + }% + }% + }}\next\opttable{}% +} + +\newif\ifpropertable + +\def\checkforpropertable#1{{% checking if there is any table material +% this is a hack to avoid underfull boxes when there is no actual alignment material in +% \halign to \hsize + \hbadness\@M + \let\noalign\trivialnoalign + \let\omit\relax + \setbox\z@=\vbox{ + \halign + {\eatone{##}&\eatone{##}.&\eatone{##}&\eatone{##}\cr + \the#1% + }% + }% + \ifnum\wd\z@>\z@ + \aftergroup\propertabletrue + \else + \aftergroup\propertablefalse + \fi +}} + +\long\def\trivialnoalign#1{} + +% macros for processing \Cee\ mode material + +%\long\def\buildstash#1{\toksa\expandafter{\the\toksa#1}} % = stashed + +\def\cleanstash{% + \ifchecktrim\errmessage{collected stash: \the\toksa}\fi + \expandafter\cleanst@sh\the\toksa\packagebox} + +\def\cleanst@sh{\let\6\testsbox\setbox0=\vbox\bgroup} + +\def\testsbox{% + \ifmmode + \let\next\relax + \else + \egroup + \ifnum\wd\z@>\z@ + \ifnum\ht\z@>\z@ + \let\next\scoopupstash + \else + \let\next\rebuildstash + \fi + \else + \let\next\rebuildstash + \fi + \fi + \next +} + +\long\def\rebuildstash#1\packagebox{\toksa{#1}\cleanstash} + +\long\def\scoopupstash#1\packagebox{} + +\def\packagebox{\egroup\ifnum\wd0>\z@\else\toksa{}\fi} + +\def\stripstash{% + \ifchecktrim\errmessage{before trimming: \the\toksa}\fi + \def\6{}\expandafter\stripst@sh\expandafter\ignorespaces\the\toksa\6\str@pst@sh} + +\def\stripst@sh{\toksa{}\stripst@shi} + +\long\def\stripst@shi#1\6{% + \toksb{#1}\futurelet\next\str@pst@sh +} + +\def\str@pst@sh{% + \ifx\next\str@pst@sh + \iftrailingreturn + \striptrim + \fi + \concat\toksa\toksb + \iftrailingreturn % not done yet + \let\next\stripagain + \else + \let\next\eatone + \fi + \trailingreturnfalse + \else + \edef\next{\toksa{\the\toksa\the\toksb\noexpand\6}}\next + \def\next{\stripst@shi\relax\ignorespaces}% + \trailingreturntrue + \fi + \next +} + +\def\stripagain#1{\stripstash} + +\newif\iftrailingreturn + +\def\striptrim{% + \ifchecktable\errmessage{trimming: \the\toksb}\fi + \edef\next{\the\toksb}% + \expandafter\striptr@m\the\toksb\relax\end +} + +\def\striptr@m + #1% \relax (from last \stripst@shi) + #2% \ignorespaces (from last \stripst@shi) + % intervening spaces + #3% \relax + #4% ? + \end{% +% \def\next{#4}% +% \ifx\next\empty +% \toksc{#3#4}\showthe\toksc + \setbox\z@\vbox{#3#4}% + \ifnum\wd\z@=\z@ + \expandafter\trimreturn\the\toksa\end + \toksb{}% + \else + \ifnum\ht\z@=\z@ + \expandafter\trimreturn\the\toksa\end + \toksb{}% + \else + \trailingreturnfalse + \fi + \fi +} + +\def\trimreturn#1\6\end{% + \toksa{#1}% +} + +\def\boxstash{% + \ifchecktrim\errmessage{stash contents: \the\toksa}\fi + $\vtop{\activateinlinec\tabskip\z@\halign{\strut\ignorespaces##\hfil\cr\the\toksa\crcr}}$} + +\def\makestashbox{\cleanstash\stripstash\boxstash} + +\newbox\indentbox + +\def\activateinlinec{% + \setbox\indentbox=\hbox{}% + \def\1{\setbox\indentbox\hbox{\box\indentbox\hbox to 3em{\hfil}}}% + \def\2{\setbox\indentbox\hbox{\box\indentbox\hbox to -3em{}}}% + \def\4{\hbox to -3em{}}% + \def\5{}% +% \let\6\cr + \def\6{% + \edef\setindentbox{% + \setbox\indentbox\hbox to\the\wd\indentbox{\noexpand\hfil}% + \copy\indentbox\ignorespaces + }% + \expandafter\crcontainer\setindentbox + }% + \def\7{% + \edef\setindentbox{% + \setbox\indentbox\hbox to\the\wd\indentbox{\noexpand\hfil}% + \copy\indentbox\ignorespaces + }% + \expandafter\crcontainerspread\setindentbox + }% + \def\8{\hskip-1em}% + \let\$\prodterm +} + +\def\crcontainer{\cr} +\def\crcontainerspread{\cr\noalign{\yskip}} + +% rough version of the term typesetting + +\def\prodterm{% + \futurelet\next\analyzepterm +} + +\def\analyzepterm{% + \ifx\next\$% + \let\next\pr@dterm + \else + \ifcat\noexpand\next0% + \let\next\pr@dterm + \else + \let\next\oldmathS + \fi + \fi + \next +} + +\def\pr@dterm#1{% + \ifx#1\$% + \def\next{\hbox{$\Upsilon$}}% + \else + \if\noexpand#1[% + \let\next\seeksym + \else + \ifnum`#1<"3A\relax + \ifnum`#1>`0\relax + \def\next{\seekno#1}% + \else + \def\next{\hbox{$\Upsilon$}#1}% + \fi + \else + \def\next{\hbox{$\Upsilon$}#1}% + \fi + \fi + \fi + \next +}% + +\let\oldmathS\$ +\let\$\prodterm + +\def\seekno{\afterassignment\printterm\tempca}% + +\def\seeksym#1]{% + \hbox{$\Upsilon\kern-1pt{}_{\rm#1}$}} + +\def\printterm{\hbox{$\Upsilon\kern-1pt{}_{\number\tempca}$}}% + +\long\def\setproduction#1{% + \def\termidxrank{5}% + \def\headeridxrank{4}% + \def\defidxrank{3}% + \def\texcsidxrank{5}% + \ninepoint + \let\returnexplicitspace\splitexplicitspace + \let\acharswitch\texcharadjust + \let\onecharswitch\texcsadjust + \showlastactionfalse + \let\actionfiller\empty + \parsevb{#1} % Stage two, start the parsing + \ifyyparsefail + {\toks0{#1}\errmessage{failed to parse: \the\toks0}}% + \else % Stage three, process the parsed table + \par\hbox{\strut}% + \typesetalltables + \fi +} + +\def\splitexplicitspace{% + \yyinput\{\}% +} + +\def\texcharadjust{ + ` {% + \yybyte{|}% + \expandafter\yycp@\expandafter`\the\yybyte\relax + \mkpurebyte + \yyreturn + } + _ {% + \yybyte{\_}% + \expandafter\yycp@\expandafter`\the\yybyte\relax + \mkpurebyte + \yyreturn + } +} + +\def\texcsadjust{ + \n {% + \yycp@=\n + \mkpurebyte + \yyreturn + } + \^^M {% + \yyinput\{\}% + } + \' {% + \expandafter\yyinput\benignescape'% + } + \\ {% + \expandafter\expandafter\expandafter\yyinput\expandafter\benignescape\benignescape% + } +}% + +% production typesetting + +\def\beginprod{% + \par + \begingroup + \b@ginprod +} + +\long\def\b@ginprod#1\endprod{% + \setproduction{#1}% + \endgroup + \par +} + +\def\beginmprod{% + $$ + \vbox\bgroup + \def\checkforpropertable##1{\propertablefalse} % so that the table is set to its natural width + \b@ginmprod +} + +\long\def\b@ginmprod#1\endmprod{% + \setproduction{#1}% + \egroup + $$% +} + +% centering productions: works for rule listing only (no token declarations, etc.) + +\def\begincprod#1\endcprod{{\def\tlskip{0 pt plus1fill}\let\tfskip\tlskip\beginprod#1\endprod}} + +% the next macro assumes that \gindex being defined implies that all the bookkeeping required +% for maintaining the index of grammar terms has been taken care of + +\ifx\gindex\UNDEFINED +\else + \termindextrue + \immediate\openout\gindex=\jobname.gdx +\fi + +% stringing all the manuals together (disabled for now) + +%\newwrite\lastpageinfo +%\newread\testeof + +%\toksa\expandafter{\fin} +%\edef\fin{\the\toksa\noexpand\savelastpagenumber} +%\def\savelastpagenumber{% +% \openout\lastpageinfo=\jobname.lpg% +% \write\lastpageinfo{\def\noexpand\contentspagenumber{\number\pageno}\pageno=\noexpand\contentspagenumber \advance\pageno by 1}% +% \write\lastpageinfo{\def\noexpand\secno{\number\secno}}% +% \closeout\lastpageinfo +%} + diff --git a/support/splint/tex/yyinput.sty b/support/splint/tex/yyinput.sty new file mode 100644 index 0000000000..d424d299d8 --- /dev/null +++ b/support/splint/tex/yyinput.sty @@ -0,0 +1,406 @@ +% Copyright 2012-2015, 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/>. + +\def\mkpurebyte{\uccode`\@=\yycp@\uppercase{\yybytepure{@}}\uccode`\@=`\@} + +\def\yyinput{\futurelet\next\yyinp@t} % get the code of the next character ... + +\def\yyinp@t{% test the code and decide whether to continue lexing the + % token or return to the parser + \ifcat\noexpand\next\bgroup + \yybreak\yyinputgroup + \else + \if\noexpand\next\space % code 32 character token is assumed to +% be an ordinary space (while category 10 tokens are not necessarily); +% the reason for this choice is the way code 32 characters are treated +% by \string (turned into `real' spaces); `funny' spaces of both kinds +% (a character that differs from a `real' space (\catcode`\ ==10 +% \number`\ ==32) in either category or character code) can be +% created, however, category 10 characters of character code other +% than 32 are very rare (and take some effort to produce), while +% category 12, character code 32 tokens are poduced as a result of +% `sanitizing' input all the time; note that the spaces are processed +% at the lowest level of the input routine and thus cannot be +% substituted by the switches below; this choice is not bullet proof +% but should suffice for most uses; in the case of more polluted +% input, an extra `sanitation' step can be performed first; if +% desired, category 10 charactes can be assumed to be spaces at this +% point, as well, although this will introduce an extra test, affecting +% the (already poor) efficiency of the input macros. + \yycp@=`\ % + \yybyte={ }% + \mkpurebyte + \yybreak@\yyskipspace % return the space + \else + \if\noexpand\next\eolletter % cannot use ^^M here since TeX will simply drop the rest of the line + \yycp@=\n + \yybyte={\n}% + \mkpurebyte + \yybreak@@\yyskipspace % return the end of line character + \else + \yybreak@@\yy@np@t + \fi + \fi + \yycontinue +} + +\chardef\n=`\^^J +\chardef\charseq1 +\chardef\charac2 +\chardef\chargroup3 + +\def\yyskipspace{\afterassignment\yyreturn\let\next= } + +\def\yyinputgroup#1{% + \yycp@=\chargroup + \yybyte={{#1}}% + \mkpurebyte + \yyreturn +} + +\newif\ifyyinputdebug + +\def\yy@np@t#1{% start lexing: + % whitespace (category 10) tokens are skipped + % automatically + \yybyte{#1}% + \ifyyinputdebug + \immediate\write16{read: \the\yybyte}% + \fi + \ifx#1\ % a space token + \yybreak\returnexplicitspace + \else + \expandafter\ischar\string#100\end + \ifchar % a single character (not a control sequence) + \ifcat\noexpand#1\noexpand~% is it an active character? + \yycp@=\charac % yes, return it + \mkpurebyte + \yybreak@@\yyreturn + \else % it is a non-active character ... + % ... or a control sequence with an empty name (obtained by \csname\endcsname or + % \enlinechar=-1 \toks0={\ + % } this case can be handled by the switch below but is ignored for the moment) + \let\default\achardefault + \yybreak@@{\switchon{\the\yybyte}\in\acharswitch}% + \fi + \else % it is a control sequence, return it + \expandafter\ischar\string#10\end + \ifchar % it is a one-char control sequence + \let\default\onechardefault + \yybreak@@{\switchon{\the\yybyte}\in\onecharswitch}% + \else + \let\default\multichardefault + \yybreak@@{\switchon{\the\yybyte}\in\multicharswitch}% + \fi + \fi + \yycontinue +} + +\chardef\explicitspacecode=`\ % + +\def\returnexplicitspace{% + \yycp@=\explicitspacecode + \mkpurebyte + \yyreturn % keep looking for a non-whitespace token +} + +\def\onecharswitch{ + \raw \n \raw {% + \yycp@=\n + \mkpurebyte + \yyreturn + } + \raw \^^M\raw {% + \returnexplicitspace + } +} + +\def\onechardefault{% + \expandafter\yycp@\expandafter`\the\yybyte\relax + \mkpurebyte + \yyreturn +}% + +\def\multicharswitch{ + \raw\stashed\raw {% + \stashnext + } + \raw\format \formatlocal\raw {% + \formatnext + } + \raw\sflush\raw {% + \sflushnext + } + \raw\yyeof\raw {% + \yycp@=\YYENDOFBUFFERCHAR\relax + \yybytepure={}% + \yyreturn + } + \raw\inputboundary\raw {% + \inputboundarynext + } + \raw\flatten \resetf \inline \skipheader\raw {% + \expandafter\yyinput\expandafter\format\expandafter{\the\yybyte}% + } + \raw\fold \breakline\raw {% + \expandafter\yyinput\expandafter\formatlocal\expandafter{\the\yybyte}% + } + \raw\break\raw {% for testing purposes + \yycp@=`\ % + \yybytepure={ }% + \yyreturn + } + \raw\squashtermstrue\raw {% + \yycp@=`\ % + \yybytepure={ }% + \squashtermstrue + \yyreturn + } + \raw\endparse \endparseinput\raw {% + \errmessage{internal error: reading past the end of the input buffer}% + } +} + +\def\multichardefault{% + \yycp@\charseq + \mkpurebyte + \yyreturn +}% + +\def\achardefault{% + \expandafter\yycp@\expandafter`\the\yybyte\relax + \mkpurebyte + \yyreturn +} + +\def\acharswitch{} + +% the following commands are only here for debugging purposes +% they slow down the input + +\setspecialcharsfrom\onecharswitch +\setspecialcharsfrom\multicharswitch +\setspecialcharsfrom\acharswitch + +\chardef\stashchar=`\ % +\chardef\formatchar=`\ % + +\newcount\stashmarker +\newcount\formatmarker + +\def\stashnext#1{% + \yybytepure{ }\yycp@\stashchar + \toksa{#1}% + \advance\stashmarker\@ne + \edef\next{\yysbyte{\noexpand\strm[\the\stashmarker]{\the\yybyte{\the\toksa}}.[\the\stashmarker]}}\next + % the extra `.' is to avoid the stripping of braces by the parameter scanning mechanism of TeX + \yybyte\expandafter{\the\yybyte{#1}}% + \yyreturn +} + +\def\formatnext#1{% + \yybytepure{ }\yycp@\formatchar + \toksa{#1}% + \advance\formatmarker\@ne + \edef\next{\yyfbyte{\noexpand\strm[\the\formatmarker]{\the\yybyte{\the\toksa}}.[\the\formatmarker]}}\next + % the extra `.' is to avoid the stripping of braces by the parameter scanning mechanism of TeX + \yybyte\expandafter{\the\yybyte{#1}}% + \yyreturn +} + +\chardef\boundarychar=`\ % + +% the following is a minimal setup of a parsing boundary + +\def\inputboundarynext#1{% `l' for left boundary + \yybytepure{ }\yycp@\boundarychar + \yybyte\expandafter{\the\yybyte{#1}}% + \yyreturn % inserting something here will effectively insert it into the input stream +} + +\def\sflushnext#1#2{% #1 is the marker + % #2 is the contents + \yybytepure{ }\yycp@\stashchar + \edef\next{\toksc{\the\yystash\the\yystashseen}}\next + \yyfifolastidx\toksc\in\toksc + \toksa{#1}\toksb{#2}% + \edef\next{\yysbyte{\noexpand\strm[\the\toksa]{\the\yybyte{\the\toksb}{\the\toksc}}.[\the\toksa]}}\next + % the extra `.' is to avoid the stripping of braces by the parameter scanning mechanism of TeX + \yybyte\expandafter{\the\yybyte{#1}{#2}}% + \yyreturn +} + +\def\yyreadfifo#1\to#2\in#3{% + \def\yyr@adfifo##1\strm[#2]##2[#2]##3\end{% + \def\yyr@@dfifo{##3}% + \ifx\yyr@@dfifo\empty + #3{}% there is no such marker in the fifo + \else + #3{##1\strm[#2]##2[#2]}% + \def\yyr@@dfifo####1\strm[#2]####2[#2]\end{#1{####1}}% strip off the inserted string + \yyr@@dfifo##3\end + \fi + }% + \expandafter\yyr@adfifo\the#1\strm[#2].[#2]\end +} + +\def\yyreadfifox#1\to#2\in#3{% read the fifo to a marker in #2 + \expandafter\yyreadfifo\expandafter#1\expandafter\to\number#2\in#3% +} + +\def\yyreadfifoxx#1\to#2\in#3{% read the fifo to a marker in #2 + \expandafter\yyreadfifo\expandafter#1\expandafter\to#2\in#3% +} + +\def\yyreadfifot#1\to#2\in#3\with#4{% read fifo with a test: + \def\yyr@adfifo##1\strm[#2]##2[#2]##3\end{% #4 is a \macro[##1]##2.[##3] which + \def\yyr@@dfifo{##3}% looks at its parameters and fills up + \ifx\yyr@@dfifo\empty % \othertoks (to be attached at the beginning of #1 + % after the initial segment has been removed) + % and \fifotoks (to be used by another macro) + #3{}% there is no such marker in the fifo + \else + \let\fifotoks#3% + \let\othertoks#1 + \let\@@strm\strm + \let\strm#4% + \fifotoks{}% + \othertoks{}% + ##1\strm[#2]##2[#2]% run all the tests + \let\strm\@@strm + \def\yyr@@dfifo####1\strm[#2]####2[#2]\end{#1\expandafter{\the\othertoks####1}}% + \yyr@@dfifo##3\end + \fi + }% + \expandafter\yyr@adfifo\the#1\strm[#2].[#2]\end +} + +\def\yyreadfifotx#1\to#2\in#3\with#4{% read the fifo to a marker in #2 + \expandafter\yyreadfifot\expandafter#1\expandafter\to\number#2\in#3\with{#4}% +} + +% an example of a sorting macro: extract all the local formatting + +\def\formatsort[#1]#2.[#3]{% clobbers \toksb, \toksc + \formatgrab#2\end + \toksc{\strm[#1]{#2}.[#3]}% + \let\default\formatdefaultact + \switchon{\the\toksb}\in\formatswitch +} + +\def\formatgrab#1#2\end{\toksb{#1}} + +\def\formatswitch{% + \formatlocal {% + \edef\next{\fifotoks{\the\fifotoks\the\toksc}}\next + } +} + +\def\formatdefaultact{% + \edef\next{\othertoks{\the\othertoks\the\toksc}}\next +} + +\def\yygrabfifoelem#1\at#2\in#3{% + \def\yyr@adfifo##1\strm[#2]##2[#2]##3\end{% + \def\yyr@@dfifo{##3}% + \ifx\yyr@@dfifo\empty + #3{}% there is no such marker in the fifo + \else + #3{\strm[#2]##2[#2]}% + \def\yyr@@dfifo####1\strm[#2]####2[#2]\end{#1{####1}}% strip off the inserted string + \yyr@@dfifo##1##3\end + \fi + }% + \expandafter\yyr@adfifo\the#1\strm[#2].[#2]\end +} + +\def\yygrabfifoelemx#1\at#2\in#3\with#4{% read the fifo to a marker in #2 + \expandafter\yygrabfifoelem\expandafter#1\expandafter\at\number#2\in#3\with{#4}% +} + +\def\yypeekfifoelem#1\at#2\in#3{% just read the first element that matches the marker + \def\yyr@adfifo##1\strm[#2]##2[#2]##3\end{% + \def\yyr@@dfifo{##3}% + \ifx\yyr@@dfifo\empty + #3{}% there is no such marker in the fifo + \else + #3{##2}% just get the contents + \fi + }% + \expandafter\yyr@adfifo\the#1\strm[#2].[#2]\end +} + +\def\yypeekfifoelemx#1\at#2\in#3\with#4{% read the fifo to a marker in #2 + \expandafter\yypeekfifoelem\expandafter#1\expandafter\at\number#2\in#3\with{#4}% +} + +\def\strmgetfirstidx[#1]#2.[#3]{\toksa{#1}} + +\def\yyfifolastidx#1\in#2{% + \let\next\strm + \let\strm\strmgetfirstidx + \toksa{}\the#1% + #2\toksa + \let\strm\next +} + +\def\z@rotest{0} +\newif\ifchar + +\def\ischar#1#2#3\end{% three parameters because #1 can be an + % \escapechar + \def\lastnamechar{#3}% + \ifx\lastnamechar\z@rotest\chartrue\else\charfalse\fi +} + +% trivial input routine + +\def\yyinputtrivial{\futurelet\next\yyinp@ttrivial} % get the code of the next character ... + +\def\yyinp@ttrivial{ + \ifcat\noexpand\next\space % category 10 token + \yycp@=`\ % + \yybyte={ }% + \mkpurebyte + \yybreak\yyskipspace % return the space + \else + \yybreak\yy@np@ttrivial + \yycontinue +} + +\def\yy@np@ttrivial#1{% + \ifcat\noexpand#1a% + \yycp@`#1% + \yybyte{#1}% + \yybytepure{#1}% + \else + \if\noexpand#1\eolletter + \yycp@=\n + \yybyte\expandafter{\eolletter}% + \mkpurebyte + \else + \ifx#1\yyeof + \yycp@=\YYENDOFBUFFERCHAR\relax + \yybyte{#1}% + \yybytepure={}% + \else + \yycp@\charseq + \mkpurebyte + \fi + \fi + \fi + \yyreturn +} diff --git a/support/splint/tex/yymisc.sty b/support/splint/tex/yymisc.sty new file mode 100644 index 0000000000..fcc38da96d --- /dev/null +++ b/support/splint/tex/yymisc.sty @@ -0,0 +1,1422 @@ +% 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/>. + +% `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} + +% 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 +} + +% creating a sequence containing all pairs from the two given sequences; +% the (long) string produced by the \diagprod macro +% lists all the elements so that each ordered pair ab where a and b are +% different elements from each of the two sets appears exactly once; +% a simple strategy for creating such strings is to build them recursively so that if +% S is a string that lists n values in this manner and s is a new item type, +% start with sSs and then add each symbol from S on either side +% in such a way that among any two consecutive symbols exactly one is s + +% these macros are used to create switch statements that use such ordered pairs +% and are not particularly general or robust; +% they are supposed to be used once in the setup stage; +% the assumption made by these mactos is that `.' or `;' never appear as elements +% of the two sets + +\def\gnxtelem#1\to#2\and#3{% + \expandafter\gnxtel@m\expandafter#2\expandafter#3\the#1.;% +} + +\def\gnxtel@m#1#2#3#4;{% + \def\next{#4}% + \ifx\next\empty + #1{}% + \else + #1{#3}% + \gnxt@l@m#2#4% + \fi +} + +\def\gnxt@l@m#1#2.{% + #1{#2}% +} + +\def\pairup{% + \gnxtelem\toksa\to\toksc\and\toksa % get the first remaining element of set A (\toksa) + \edef\elemofA{\the\toksc}% + \ifx\elemofA\empty % no more elements in A + \let\next\relax + \else + \ifx\elemofA\lastelemofB % the current element of A is the same as the last element of B + \edef\next{\the\toksa}% + \ifx\next\empty % it is the last remaining element of A + \expandafter\p@ir@p\the\toksb.% form all pair of \the\toksc with elements in B except the first one + \else + \concat\toksa\toksc % move it to the end of A + \fi + \let\next\pairup + \else + \expandafter\pair@p\the\toksb.% form all pairs of \the\toksc with elements in B + \let\next\pairup + \fi + \fi + \next +} + +\def\dotcontainer{.} + +\def\pair@p#1{% + \def\next{#1}% + \ifx\next\elemofA % the next element of B is the current element of A + \ifx\next\lastelemofB % it is the last element of B + % we can arrive here only if 1) B has more than one element and + % 2) \elemofA is the last remaining element of A + \edef\next{\toksd{\the\toksd\the\tokse}}\next + \let\next\eatone % eat the remaining dot + \else + \removeelem\elemofA\from\toksb % remove it from B + \let\next\pair@p + \fi + \else + \ifx\next\dotcontainer % no more elements in B + \let\next\relax + \else + \toksf{#1}% + \edef\next{\toksd{\the\toksd\the\toksc\the\toksf}}\next + %\showthe\toksd + \let\next\pair@p + \fi + \fi + \next +} + +\def\p@ir@p#1{% + \def\next{#1}% + \ifx\next\elemofA % the next element of B is the current element of A + % this can only happen if B consists of a single element + \let\next\eatone + \else + \toksf{#1}% + \edef\next{\toksd{\the\toksd\the\toksf}}\next + \let\next\pair@p + \fi + \next +} + +\def\removeelem#1\from#2{% #1 should be a sequence containing the element + % #2 is the token register + \expandafter\def\expandafter\r@moveelem\expandafter##\expandafter1#1##2.{% + \def\next{##2}% + \ifx\next\empty % there was no such element + \errmessage{Could not find \expandafter\string#1 in \the#2}% + \else + \expandafter\def\expandafter\r@mov@elem\expandafter####\expandafter1#1{% + #2{##1####1}% + }\r@mov@elem##2% + \fi + }% + \expandafter\expandafter\expandafter\r@moveelem\expandafter\the\expandafter#2#1.% +} + +% the intersection of A and B should be at the end of A: + +\def\pushintersect{% + \gnxtelem\toksf\to\toksc\and\toksf % get the first remaining element of set A (\toksa) + \edef\next{\the\toksc}% + \ifx\next\empty % there are no elements left in A + \let\next\relax + \else + \expandafter\def\expandafter\p@shintersect\expandafter##\expandafter1\the\toksc##2.{% + \def\next{##2}% + \ifx\next\empty % there was no such element in the other set + \edef\next{\toksa{\the\toksc\the\toksa}}\next % append it to the front + \else + \edef\next{\toksa{\the\toksa\the\toksc}}\next % append it to the back + \fi + }% + \expandafter\expandafter\expandafter\p@shintersect\expandafter\the\expandafter\toksb\the\toksc.% + \let\next\pushintersect + \fi + \next +} + +\def\diagprod#1#2\in#3{% + \toksa\expandafter{#1}% + \toksb\expandafter{#2}% + \gnxtelem\toksb\to\tokse\and\toksb % \tokse is a selected element in set B (\toksb) + \concat\toksb\tokse % now \tokse is the last element of B + \toksf\toksa\toksa{}% + \pushintersect % prepare the sequence representing set A so that the intersection elements are in the tail + \edef\lastelemofB{\the\tokse}% the last element of B + \toksd\expandafter{\the\tokse}% future sequence pairs + \pairup + \edef#3{\the\toksd}% +} + +% namespace management for macros +% note that if one of the sequences were made \let\name. the macros would break; +% this can be fixed by using a more sophisticated comparison but was decided against +% in the interest of efficiency; the old version (that used a control sequence +% as a `stop marker') was more prone to this bug. + +\def\savecs#1#2{\s@vecs{#1}#2.} + +\def\s@vecs#1#2{% + \ifx#2.% + \yybreak{}% + \else + \yybreak{% + \expandafter\let\csname '#1'[\expandafter\eatone\string#2]\endcsname#2% + \s@vecs{#1}% + }% + \yycontinue +} + +\def\restorecs#1#2{\r@storecs{#1}#2.} + +\def\r@storecs#1#2{% + \ifx#2.% + \yybreak{}% + \else + \yybreak{% + \expandafter\let\expandafter#2\csname '#1'[\expandafter\eatone\string#2]\endcsname + \r@storecs{#1}% + }% + \yycontinue +} + +\def\hidecs#1{\h@decs#1.} + +\def\h@decs#1{% + \ifx#1.% + \yybreak{}% + \else + \yybreak{% + \let#1\relax + \h@decs + }% + \yycontinue +} + +\def\savehcs#1#2{\savecs{#1}{#2}\hidecs{#2}} + +\def\savecslist#1#2{% + \expandafter\s@vecslist\expandafter{#2}{#1}% +} + +\def\s@vecslist#1#2{% + \savecs{#2}{#1}% +} + +\def\restorecslist#1#2{% + \expandafter\r@storecslist\expandafter{#2}{#1}% +} + +\def\r@storecslist#1#2{% + \restorecs{#2}{#1}% +} + +% a twist on the macros above: save control sequences with a postfix + +\def\savecsx#1#2{\s@vecsx{#1}#2.} + +\def\s@vecsx#1#2{% + \ifx#2.% + \yybreak{}% + \else + \yybreak{% + \expandafter\s@vecsxlet\expandafter#2\csname\expandafter\defprefix\expandafter\eatone\string#2\defpostfix\endcsname{#1}% + \s@vecsx{#1}% + }% + \yycontinue +} + +\def\s@vecsxlet#1#2{% + \expandafter\let\csname '#2'[\expandafter\defprefix\expandafter\eatone\string#1\defpostfix]\endcsname +} + +\def\restorecsx#1#2{\r@storecsx{#1}#2.} + +\def\r@storecsx#1#2{% + \ifx#2.% + \yybreak{}% + \else + \yybreak{% + \expandafter\r@storecsxlet\expandafter#2\csname '#1'[\expandafter\defprefix\expandafter\eatone\string#2\defpostfix]\endcsname + \r@storecsx{#1}% + }% + \yycontinue +} + +\def\restorecsxlist#1#2{% + \expandafter\r@storecsxlist\expandafter{#2}{#1}% +} + +\def\r@storecsxlist#1#2{% + \restorecsx{#2}{#1}% +} + +\def\r@storecsxlet#1{% + \expandafter\let\csname\expandafter\defprefix\expandafter\eatone\string#1\defpostfix\endcsname +} + +\def\hidecsx#1{\h@decsx#1.} + +\def\h@decsx#1{% + \ifx#1.% + \yybreak{}% + \else + \yybreak{% + \expandafter\let\csname\expandafter\defprefix\expandafter\eatone\string#1\defpostfix\endcsname\relax + \h@decsx + }% + \yycontinue +} + +\def\savehcsx#1#2{\savecsx{#1}{#2}\hidecsx{#2}} + +\def\defx#1{% defining sequences as above + \toksa\expandafter{% + \csname\expandafter\defprefix\expandafter\eatone\string#1\defpostfix\endcsname}% + \afterassignment\d@fx + \expandafter\def\the\toksa +} + +\def\d@fx#1{% + \toksb{#1}\edef\next{\noexpand\savehcs{\the\toksb}\the\toksa}\next +} + +\def\defy#1#2#{% in addition to the definition of the contorl sequence + % in the appropriate namespace, this macro adds a + % preamble, a postamble and a `this' type macro; this + % will mostly be used with indexing \TeX\ control sequences + \tokse{\def\thisname{#1}\edef\thisnamex{\expandafter\eatone\string#1}}% + \toksa\expandafter{% + \csname\expandafter\defprefix\expandafter\eatone\string#1\defpostfix\endcsname}% + \toksc\expandafter{\expandafter\def\the\toksa#2}% + \afterassignment\d@f@ + \toksd=% +} + +\def\d@f@{% + \appendl\toksd{\the\tokse}% + \tokse\expandafter{\defypreamble}% + \appendl\toksd{\the\tokse}% + \tokse\expandafter{\defypostamble}% + \appendr\toksd{\the\tokse} + \toksd\expandafter{\expandafter{\the\toksd}}% + \concat\toksc\toksd + \afterassignment\d@fy + \the\toksc +} + +\def\d@fy#1{% + \toksb{#1}\edef\next{\noexpand\savehcs{\the\toksb}\the\toksa}\next +} + +% dynamic typing macros + +\def\defp#1#2#{% flexible dynamic type checking + \toksa\expandafter\expandafter\expandafter{\yyuniontag#1}% + \expandafter\edef\yyuniontag{\the\toksa}% + \def#1#2{\errmessage{unexpected type: \string#1 in namespace <\currentyyunionnamespace>}}% + \savecs\parserstrictnamespace#1% + \toksa{#2}% + \edef#1{\the\toksa}% + \savecs\parserprototypesnamespace#1% + \def#1#2% +} + +% define the macro with checking of the prototype + +\def\defu#1#2#{% + \restorecs\parserprototypesnamespace#1% + \toksa{#2}% + \edef\next{\the\toksa}% + \ifx#1\next + \yybreak{\def#1#2}% + \else + \toksb\expandafter{#1}% + \yybreak{% + {\newlinechar=`^^J% + \errhelp{the prototype of #1is from <parser-strict:headers>^^J% + you might want to look for a \defp#1line... somewhere}% + \errmessage{macro definition of \noexpand#1 + does not match its prototype:^^J + \the\toksa\space (should be \the\toksb)}% + }% + }% + \yycontinue +} + +% define the macro with an automatic prototype + +\def\defc#1{% + \restorecs\parserprototypesnamespace#1% + \expandafter\def\expandafter#1#1% +} + +\def\t@yyunion#1#2{\def\currentyyunionnamespace{#2}\savecslist{#2}#1} +\def\toyyunion#1{\expandafter\t@yyunion\yyuniontag{#1}} + +{\catcode`\ =13 \aftergroup\def\aftergroup\activespace\aftergroup{\aftergroup \aftergroup}}% active space +{\catcode`\% =12 \aftergroup\def\aftergroup\harmlesscomment\aftergroup{\aftergroup%\aftergroup}}% not really a comment +{\catcode`\{ =12 \catcode`\[=1 \aftergroup\def\aftergroup\lbchar\aftergroup[\aftergroup{\aftergroup}}% not really a brace +{\catcode`\} =12 \catcode`\]=2 \aftergroup\def\aftergroup\rbchar\aftergroup{\aftergroup}\aftergroup]]% not really a brace +{\catcode`\_=12 \aftergroup\def\aftergroup\uscoreletter\aftergroup{\aftergroup_\aftergroup}} +{\catcode`\^^M=12 \aftergroup\def\aftergroup\eolletter\aftergroup{\aftergroup^^M\aftergroup}}% end of line, ... not really +{\catcode`\|=0\catcode`\\=12 |aftergroup|def|aftergroup|benignescape|aftergroup{|aftergroup\|aftergroup}}% not an escape +{\catcode`\#=12 \aftergroup\def\aftergroup\hashletter\aftergroup{\aftergroup#\aftergroup}}% not a parameter token + +% token name input + +\def\doascii#1{% + \tempca=\z@ \tempcb=\@cclvi + \let\yyasciicc\empty + \let\sts\relax + \loop + \edef\yyasciicc{\sts{\the\catcode\tempca}\yyasciicc}% + \catcode\tempca=#1 + \advance\tempca\@ne + \ifnum\tempca<\tempcb\relax + \repeat + \catcode`\ =10 % keep normal spaces (otherwise \string will convert the category to 10) + %\catcode`\^^M=5 % if newline is to be preserved + \catcode`\^^M=12 % to match \eolletter +} + +\def\undoascii{% + \tempca=\@cclv + \let\sts\undoacatcode + \yyasciicc\def\yyasciicc{}% +} + +\def\undoacatcode#1{\catcode\tempca=#1\advance\tempca\m@ne} + +% yytname macros + +\def\endcontainer{\end}% +\def\aaddname{\addname} + +\def\addname{% + \toksb{}% + \@ddname +} + +\def\@ddname#1{% + \def\next{#1}% + \ifx\next\aaddname + \expandafter\edef\csname term\parsernamespace\the\toksb \endcsname{\the\tempca}% + \appendtoyytname + \advance\tempca1\relax + \let\next\addname + \else + \ifx\next\endcontainer + \expandafter\edef\csname term\parsernamespace\the\toksb \endcsname{\the\tempca}% + \appendtoyytnamelast + \let\next\relax + \else + \ifnum#1=`\_\relax + \uccode`\.=#1\relax + \uppercase{\toksa{.}}% + \uccode`\.=`\.% + \else + \ifnum#1=`\-\relax + \toksa{-}% + \else + \ifnum#1=`\ \relax + \toksa{ }% + \else + \uccode`\@=#1\relax + \uppercase{\toksa{@}}% + \uccode`\@=`\@\relax + \fi + \fi + \fi + \concat\toksb\toksa + \let\next\@ddname + \fi + \fi + \next +} + +\def\appendtoyytname{% + \concat\yytname\toksb + \toksa{\or}% + \concat\yytname\toksa +} + +\def\appendtoyytnamelast{% + \concat\yytname\toksb +} + +\def\print#1{{\endlinechar=`\^^J\immediate\write16{#1}}} + +% token and state setup +% these are defined for a specific (though dynamic) namespace only + +\def\tokenset#1#2{% + \expandafter\edef\csname token\parsernamespace \fgetelemof{yytname}\at{#1}\endcsname{#2}% +} + +\def\settokens{% + \tempca=1\relax + \loop + \tempcb=\fgetelemof{yytranslate}\at\tempca\relax % important \relax! + \tokenset\tempcb{\the\tempca}% + \advance\tempca\@ne + \ifnum\YYTRANSLATESIZE>\tempca + \repeat + \relax +} + +\def\stateset#1#2{% + \expandafter\def\csname flexstate\parsernamespace #1\endcsname{#2}% +} + +% token equivalence for bootstrap + +\def\tokeneq#1#2{% + \toksa{}% + \numberstochars#2\end + \toksa\expandafter{\csname token\parsernamespace\the\toksa\endcsname}% + \toksb\expandafter{\csname token\parsernamespace#1\endcsname}% + \edef\next{\let\the\toksb\the\toksa}\next +}% + +\def\numberstochars#1{% + \ifx\end#1% + \yybreak{}% + \else + \uccode`.=#1\relax + \uppercase{\toksa\expandafter{\the\toksa.}}% + \uccode`.=`\.% + \yybreak{\numberstochars}% + \yycontinue +} + +\def\numberstocharsandspaces#1{% same as above but turn \number`\ into a real space token + \ifx\end#1% + \yybreak{}% + \else + \ifnum#1=` \relax + \yybreak@{% + \expandafter\expandafter\expandafter + \toksa\expandafter\expandafter\expandafter{\expandafter\the\expandafter\toksa\space}\numberstocharsandspaces}% + \else + \uccode`.=#1\relax + \uppercase{\toksa\expandafter{\the\toksa.}}% + \uccode`.=`\.% + \fi + \yybreak{\numberstocharsandspaces}% + \yycontinue +} + + +% other parser and lexer variables + +\newtoks\pinittoks % a token register to hold the code that switches the parser to a different namespace + +% tables + +\def\newtable@full#1{% + \toksa{\csname newtoks\endcsname}% + \expandafter\the\expandafter\toksa\csname #1\parsernamespace\endcsname + \edef\next{\let\csname #1\endcsname\csname #1\parsernamespace\endcsname}\next + \toksa\expandafter{\next}\concat\pinittoks\toksa + \csname #1\parsernamespace\endcsname=% +} + +\let\newtable\newtable@full % optimization can change this + +% constants + +\def\constset#1#2{% + % a \mathchardef would be nicer but it cannot handle negative numbers + \expandafter\def\csname #1\parsernamespace\endcsname{#2}% + \toksa\expandafter{\csname #1\endcsname}% + \toksb\expandafter{\csname #1\parsernamespace\endcsname}% + \edef\next{\let\the\toksa\the\toksb}\next + \toksa\expandafter{\next}\concat\pinittoks\toksa +} + +\def\uconstset#1#2{% + % a \mathchardef for positive constants + \expandafter\mathchardef\csname #1\parsernamespace\endcsname=#2 % + \toksa\expandafter{\csname #1\endcsname}% + \toksb\expandafter{\csname #1\parsernamespace\endcsname}% + \edef\next{\let\the\toksa\the\toksb}\next + \toksa\expandafter{\next}\concat\pinittoks\toksa +} + +\def\charset#1#2{% + \expandafter\chardef\csname #1\parsernamespace\endcsname=#2\relax% + \toksa\expandafter{\csname #1\endcsname}% + \toksb\expandafter{\csname #1\parsernamespace\endcsname}% + \edef\next{\let\the\toksa\the\toksb}\next + \toksa\expandafter{\next}\concat\pinittoks\toksa +} + +% switch macro + +\def\stashswitch#1{% + \toksa\expandafter{\csname #1\endcsname}% + \toksb\expandafter{\csname #1\parsernamespace\endcsname}% + \edef\next{\let\the\toksb\the\toksa}\next + \edef\next{\let\the\toksa\the\toksb}% + \toksa\expandafter{\next}\concat\pinittoks\toksa +} + +% parser and lexer state control + +\def\settokreg#1{% + \toksa{\csname newtoks\endcsname}% + \expandafter\the\expandafter\toksa\csname #1\parsernamespace\endcsname + \edef\next{\let\csname #1\endcsname\csname #1\parsernamespace\endcsname}\next + \toksa\expandafter{\next}\concat\pinittoks\toksa +} + +\def\setcntreg#1{% + \toksa{\csname newcount\endcsname}% + \expandafter\the\expandafter\toksa\csname #1\parsernamespace\endcsname + \edef\next{\let\csname #1\endcsname\csname #1\parsernamespace\endcsname}\next + \toksa\expandafter{\next}\concat\pinittoks\toksa +} + +\def\setnulstack#1{% + \toksa\expandafter{\csname #1\endcsname}% + \toksb\expandafter{\csname #1\parsernamespace\endcsname}% + \edef\next{\let\the\toksb\noexpand\empty}\next + \edef\next{\let\the\toksa\the\toksb}\next + \toksa\expandafter{\next}\concat\pinittoks\toksa + \setcntreg{#1<count>}% this is only needed for the accelerated stack +} + +\def\setcurrentcs#1{% + \toksa\expandafter{\csname #1\endcsname}% + \toksb\expandafter{\csname #1\parsernamespace\endcsname}% + \edef\next{\let\the\toksb\the\toksa}\next + \edef\next{\toksa{\let\the\toksa\the\toksb}}\next + \concat\pinittoks\toksa +} + +\def\newparserstate{% + \setcntreg{yytoken}% + \setcntreg{yystate}% + \setcntreg{yyn}% + \setcntreg{yylen}% + % + \setcntreg{yyilen}% depth of stack before an inline action + % \yyval and \yylval will be token registers + \settokreg{yyval}% + \settokreg{yylval}% + \setnulstack{yyssa}% + \setnulstack{yyvsa}% +} + +\def\newlexerstate{% + \settokreg{yytext}% + \settokreg{yytextseen}% + \settokreg{yybyte}% + \settokreg{yyfutureyytext}% token register used to save read text in eob macros + % + \settokreg{yytextpure}% % the registers that serve the same role + \settokreg{yytextseenpure}% % as \yytext et al except they collect characters + \settokreg{yybytepure}% % with category code 11 (letter) and the same character code + % + \settokreg{yyformat}% % the registers that serve the same role + \settokreg{yyformatseen}% % as \yytext et al except they collect format + \settokreg{yyfbyte}% % commands + % + \settokreg{yystash}% % the registers that serve the same role + \settokreg{yystashseen}% % as \yytext et al except they collect stashed + \settokreg{yysbyte}% % tokens + % + \setcntreg{yycurrentstate}% + \setcntreg{yycurrentstatelocal}% a state variable used in eob macros + \setcntreg{yyc}% + \setcntreg{yyclocal}% another eob macro variable + \setcntreg{yyact}% + \setcntreg{yyg@yyinit}% + \setcntreg{yyg@yystart}% + \setcntreg{yyg@yylastacceptingstate}% + \setcntreg{yycp@}% + \setcntreg{YYATBOL}% + \setcntreg{yychar}% + % + \setcntreg{yytextlastchar}% + \setcntreg{yytextseenlastchar}% + % + \setcntreg{yyfmark}% % the last marker in the current token + \setcntreg{yyfmarklast}% + \setcntreg{yysmark}% + \setcntreg{yysmarklast}% + \setnulstack{yystatestack}% + \setcurrentcs{setflexstates}% + \setcurrentcs{ifyytextbackup}% this is purely to record the recovery command in \pinittoks +} + +\def\savestatelist#1{% this elaborate definition is needed to ensure that `throwaway token registers' like \toksa + % survive the namespace switch + \edef\next{\expandafter\expandafter\expandafter + \let\expandafter\expandafter\expandafter\noexpand\expandafter\expandafter\csname #1\parsernamespace\endcsname + \expandafter\noexpand\csname #1\endcsname}\next +} + +\def\savefullstate{% + \savestatelist{yyssa}% + \savestatelist{yyvsa}% + \savestatelist{yystatestack}% + \savestatelist{ifyytextbackup}% buffer +} + +% use \pinittoks to compose a `parser restore' macro along with +% \let\yyvsa\yyvsa[parser namespace] and \let\yyssa\yyssa[parser namespace]; +% `parser save' macro only has to set up \yy?sa[parser namespace]'s; +% if a fully reentrant parser is required, use the macros above to save the contents of +% all the variables by redefining \settokreg and \setcntreg and saving \yy?sa stacks + +% switch and dfa macros + +%% character class checking: #1 is the character, #2 is the character class control sequence + +\newif\ifinclass + +\def\ifclassof#1\is#2{% + \tempca#1\relax + \expandafter\checkclass#2\end +} + +\def\checkclass#1{% + \ifx#1\end + \let\next\relax + \inclassfalse + \else + \ifnum`#1=\tempca + \let\next\classend + \inclasstrue + \else + \let\next\checkclass + \fi + \fi + \next +} + +\tempca=\catcode`\^^A +\catcode`\^^A=12 % so that the characters inside sequences get the appropriate catcodes + +\def\classend#1\end{} + +\def\setspecialchars#1{% + \toksa{}% + \tempca=`\ % + \loop + \advance\tempca\@ne + \tempcb=\fgetelemof{yytranslate}\at\tempca\relax + \ifnum\tempcb>\tw@ + \tempcb=\uccode`^^A\uccode`^^A=\tempca + \uppercase{\edef\next{\toksa{\the\toksa^^A}}}\next + \uccode`^^A=\tempcb + \fi + \ifnum\tempca<\@cclv + \repeat + \edef#1{\the\toksa}% +} + +\newif\iftraceswitchlabels +\traceswitchlabelstrue + +\def\setspecialcharsfrom#1{% + \toksb\expandafter{#1}% + \iftraceswitchlabels + \edef\next{\toksa{\expandafter\noexpand\csname <state: \expandafter\eatone\string#1>\endcsname}}\next + \expandafter\let\the\toksa\empty + \else + \toksa{}% + \fi + \tempcb=\uccode`\^^A\relax + \expandafter\s@tspecialcharsfrom\the\toksb\end + \edef#1{\the\toksa}% + \uccode`\^^A=\tempcb +} + +\def\s@tspecialcharsfrom{% + \futurelet\next\s@tsp@cialcharsfrom +}% + +\def\s@tsp@cialcharsfrom{% + \ifcat\space\noexpand\next + \expandafter + \s@tsp@cialch@rsfr@m + \else + \expandafter + \s@tsp@cialch@rsfrom + \fi +} + +\def\s@tsp@cialch@rsfr@m{% + \afterassignment\s@tspecialcharsfrom\let\next= % this is the optional space +} + +\def\s@tsp@cialch@rsfrom#1{% + \toksb{#1}% + \ifx\next\bgroup % this is an action group + \edef\next{\toksa{\the\toksa{\the\toksb}}}\next + \let\next\s@tspecialcharsfrom + \else + \let\default\specchardefault + \iftracedfa % to avoid conflicts while tracing actions + \tracedfafalse + \switchon{\the\toksb}\in\speccharswitch + \tracedfatrue + \else + \switchon{\the\toksb}\in\speccharswitch + \fi + \fi + \next +}% + +\def\speccharswitch{% + \end {% + \let\next\relax + } + \raw \rawcode \classexpand \meanit \statecomment {% + % + } +} + +\def\specchardefault{% + \uccode`\^^A\expandafter`\the\toksb + \uppercase{\edef\next{\toksa{\the\toksa^^A}}}\next + \let\next\s@tspecialcharsfrom +} + +\def\raw#1\raw{% + \toksb{#1}% + \concat\toksa\toksb + \s@tspecialcharsfrom +} + +\def\rawcode#1{% + \ifx#1\rawcode + \let\next\s@tspecialcharsfrom + \else + \uccode`\^^A=#1\relax + \uppercase{\edef\next{\toksa{\the\toksa^^A}}}\next + \let\next\rawcode + \fi + \next +} + +\def\classexpand#1{% + \toksb\expandafter{#1}% + \concat\toksa\toksb + \s@tspecialcharsfrom +} + +\def\meanit#1{% + \toksb\expandafter{\meaning#1}% + \concat\toksa\toksb + \s@tspecialcharsfrom +} + +\def\statecomment#1\statecomment{\edef\next{\toksa{\the\toksa + \expandafter\noexpand\csname (#1)\endcsname}}\next\s@tspecialcharsfrom} + +\def\putother#1\in#2{% + \tempca=\catcode`\^^A\relax + \tempcb=\uccode`\^^A\relax + \uccode`\^^A=#1\relax + \uppercase{\edef\next{#2{^^A}}}\next + \uccode`\^^A=\tempcb +} + +% listing all the rules in a macro + +\def\listrules{% + \tempcb=\tw@ % start with a user-set rule + \loop + \listrule + \ifnum\tempcb<\YYNRULES\relax + \advance\tempcb\@ne + \repeat +} + +\catcode`\$=11 + +\def\listrule{% + \tempcc=\fgetelemof{yyrone}\at\tempcb\relax % get the symbol this rule derives + \edef\next{\toksa{\fgetelemof{yytname}\at\tempcc}}\next + \expandafter\checkforimplicit\the\toksa $@\end%$ + \ifimplicit + \edef\next{\toksc{\noexpand\ih{\the\toksa}}}\next + \edef\next{\toksa{\noexpand\implicitrule[\the\toksa]}}\next + \else + \edef\next{\toksa{\the\tempcc}}\next + \toksc{}% + \fi + \appendr\toksa{:}% + \toksb{}% + \tempcc=\fgetelemof{yyprhs}\at\tempcb\relax + \tempcd=\fgetelemof{yyrhs}\at\tempcc\relax + \listr@le + \edef\next{\newsymswitch{\the\newsymswitch\the\toksa\def{\the\toksc:\the\tempcb}\noexpand\ruleor}}\next +} + +\def\implicitsymbol#1{}% + +\newif\ifimplicit + +\def\listr@le{% + \ifnum\tempcd>\m@ne + \ifnum\tempcd<\YYNTOKENS\relax % it is a terminal + \edef\next{\toksb{\the\tempcd}}\next + \else + \edef\next{\toksb{\fgetelemof{yytname}\at\tempcd}}\next + \expandafter\checkforimplicit\the\toksb $@\end%$ + \ifimplicit + \appendl\toksc{\noexpand\imn{\the\toksb}} + \toksb{@implicit@}% + \else + \edef\next{\toksb{\the\tempcd}}\next + \fi + \fi + \appendr\toksa{ }\concat\toksa\toksb + \advance\tempcc\@ne + \tempcd=\fgetelemof{yyrhs}\at\tempcc\relax + \let\next\listr@le + \else % this is the end of the rhs + \let\next\relax + \fi + \next +} + +\def\checkforimplicit#1$@#2\end{% $ + \def\next{#1}% + \ifx\next\empty + \implicittrue + \else + \implicitfalse + \fi +} +\catcode`\$=3 + +% symbol switch macros + +\newtoks\oneimplicitrule + +% inline explicit symbolic names + +\def\itermstack#1#2{% + \toksa=\oneimplicitrule + \appendl\toksa{\noexpand\lhs{#1}{#2}}% + \expandafter + \yypush + \expandafter + {\the\toksa}\on\yyirulestack + \appendr\oneimplicitrule{\noexpand\implicitterm{#1}{#2}}% +} + +\def\makeisymnames#1:#2\end{% + \tempcc=#2\relax + \def\next{#1}% + \ifx\next\empty + \relax + \else + \let\imn\assigninames + \fi + #1% +} + +\def\assigninames#1{% + \yypop\yyirulestack\into\toksc + \def\sts##1{##1}% + \savehcs{symn}{\term\lhs\implicitterm\onerule}% + \edef\next{\noexpand\onerule{\the\toksc}}% + \edef\next{\toksc{\next}}\next + \toksb{\implicitrule[#1]:\def}% + \yyreplacestring\toksb\in\newsymswitch\with\toksc + \restorecs{symn}{\term\lhs\implicitterm\onerule}% +} + +\def\oneruleid#1#2{% + \oneimplicitrule{}% + \yyinitstack\yyirulestack + \toksb{#1}% + #1% + \makeisymnames#2\end +} + +\def\termexsymname#1#2{% + \appendr\oneimplicitrule{\noexpand\term{#1}{#2}}% +} + +\def\iruleplaceholder#1:\def#2{} + +\def\setexplicitinlinerules#1{% + \let\onerule\oneruleid + \let\term\termexsymname + \let\lhs\eattwo + \let\implicitterm\itermstack + \let\ruleor\relax + \let\ih\eatone + \let\imn\eatone + \let\implicitrule\iruleplaceholder + \the#1% set explicit names +} + +\catcode`\^^A=\tempca + +\def\makesymrefs#1{% #1 is the symbolic rule switch + \let\ruleor\or + \nameflagtoks{}% + \edef\next{\setsncommands{\noexpand\or\space\harmlesscomment\space (rule 0)^^J% + \noexpand\or\space\harmlesscomment\space (rule 1)^^J}}\next + \edef\next{\unsetsncommands{\noexpand\or\space\harmlesscomment\space (rule 0)^^J% + \noexpand\or\space\harmlesscomment\space (rule 1)^^J}}\next + \yyn=\tw@ + \loop + \yylen=\fgetelemof{yyrtwo}\at\yyn\relax + \ifnum\yylen>\z@ + \else + \yylen=\fgetelemof{yyrthree}\at\yyn\relax + \fi + \xm@kesymrefs#1% + \xm@k@symrefs#1% + \addseparator + \ifnum\yyn<\YYNRULES + \advance\yyn\@ne + \repeat +} + +% these macros are here to hide \else and \fi tokens + +\def\xm@kesymrefs#1{\expandafter\m@kesymrefs\expandafter\yyn\the#1\else\fi} % explicit names +\def\xm@k@symrefs#1{\expandafter\m@k@symrefs\expandafter\yyn\the#1\else\fi} % implicit names + +\def\m@kesymrefs#1{% + \let\onerule\rulesymsetup + \ifcase#1\or\or % skip the first two rules +} + +\def\m@k@symrefs#1{% + \let\onerule\r@lesymsetup + \ifcase#1\or\or % skip the first two rules +} + +\def\addseparator{% + \sprintrule\yyn\to\toksa + \edef\next{\setsncommands{\the\setsncommands\noexpand\or\space\harmlesscomment\the\toksa^^J}}\next + \edef\next{\unsetsncommands{\the\unsetsncommands\noexpand\or\space\harmlesscomment\the\toksa^^J}}\next + \the\nameflagtoks + \nameflagtoks{}% +} + +\def\rulesymsetup#1#2{% + \let\term\termsymname + \let\lhs\lhssymname + \let\implicitterm\term + \tempca\@ne + #1% set explicit names +} + +\newtoks\setsncommands +\newtoks\unsetsncommands + +\def\termsymname#1#2{% set the symbolic name, if it is nonempty + \def\next{#2}% + \ifx\next\empty + \else % there is a symolic name + \expandafter\ifx\csname$[#2]\endcsname\relax% i$ this name unassigned? + \setnameflag{#2}\end % ... this name has been explicitly set + \setuprefs{#2}{\the\tempca}% + \else + \errmessage{ambiguous symbolic name: #2}% + \fi + \fi + \advance\tempca\@ne +} + +\newtoks\nameflagtoks + +\def\setnameflag#1#2{% + \toksa\expandafter{\csname$[#1]sym\endcsname}% $ + \edef\next{\let\the\toksa\noexpand#2}\next + \appendr\nameflagtoks{\noexpand\unsetnameflag{#1}}% +} + +\def\unsetnameflag#1{% + \toksa\expandafter{\csname$[#1]sym\endcsname}% $ + \edef\next{\let\the\toksa\relax}\next +} + +\def\unsetsymname#1{% + \toksa\expandafter{\csname$[#1]\endcsname}% $ + \edef\next{\let\the\toksa\relax}\next +} + +\def\unsetsym#1{% + \toksa\expandafter{\csname$[#1]\endcsname}% $ + \toksb\expandafter{\csname$$[#1]\endcsname}% $ + \edef\next{\let\the\toksa\relax\let\the\toksb\relax}\next +} + +\def\lhssymname#1#2{% set an explicit symbolic name for the left hand side + \setuplhsref{#2}% + \setnameflag{#2}\end % signal that this name has ben explicitly set +} + +% the code below is just an example. One has to figure out how to record percent symbols and other +% dangerous \TeX\ symbols; it is rather slow, a faster two stage scheme can be envisioned +% where the first stage builds the command while iterating over the rule numbers; this is left as an exercise. + +\let\hc\harmlesscomment +\let\uu\space +\def\setuprefs#1#2{% + \expandafter\let\csname$[#1]\endcsname.% $o the \ifx ... \relax test makes sense ... + \appendr\nameflagtoks{\noexpand\unsetsymname{#1}}% clean it up later + \toksa{}\expandafter\charstonumbers#1\end + \edef\next{\toksb{\space\space\noexpand\setsym{\the\toksa}{#2}\hc^^J\uu\uu\hc\hc\hc\uu#1 --> #2^^J}}\next + \edef\next{\toksc{\space\space\noexpand\unsetsym{\the\toksa}\hc^^J\uu\uu\hc\hc\hc\uu#1 --> \relax^^J}}\next + \concat\setsncommands\toksb + \concat\unsetsncommands\toksc +}% + +\def\setuplhsref#1{% + \def\next{#1}% + \ifx\next\empty + \else + \expandafter\let\csname$[#1]\endcsname.% $o the \ifx ... \relax test makes sense ... + \appendr\nameflagtoks{\noexpand\unsetsymname{#1}}% clean it up later + \toksa{}\expandafter\charstonumbers#1\end + \edef\next{\toksb{\uu\uu\noexpand\setlhs{\the\toksa}\hc^^J\uu\uu\hc\hc\hc\uu#1 --> $$^^J}}\next + \edef\next{\toksc{\uu\uu\noexpand\unsetsym{\the\toksa}\hc^^J\uu\uu\hc\hc\hc\uu#1 --> \relax^^J}}\next + \concat\setsncommands\toksb + \concat\unsetsncommands\toksc + \fi +}% + +\def\sprintrule#1\to#2{% + \tempcc=#1\relax + \tempcd=\fgetelemof{yyrone}\at\tempcc\relax + \edef\ruleline{\space(rule \number#1)\space\fgetelemof{yytname}\at\tempcd:}% + \tempcd=\fgetelemof{yyprhs}\at\tempcc\relax + \tempcc=\fgetelemof{yyrhs}\at\tempcd\relax + \ifnum\tempcc>\m@ne + \fillruleline + \else + \edef\ruleline{\ruleline\space<empty>}% + \fi + #2\expandafter{\ruleline}% +} + +\def\fillruleline{% + \edef\ruleline{\ruleline\space\fgetelemof{yytname}\at\tempcc}% + \advance\tempcd\@ne + \tempcc=\fgetelemof{yyrhs}\at\tempcd\relax + \ifnum\tempcc>\m@ne + \let\next\fillruleline + \else + \let\next\relax + \fi + \next +} + +\def\r@lesymsetup#1#2{% + \let\term\termsymextra + \let\lhs\lhssymextra + \let\implicitterm\term + \tempca=\@ne + #1% set implicit names +} + +\def\termsymextra#1#2{% set an implicit symbolic name: + % 1) if it has not been defined yet, define it + % 2) if it is defined implicitly, make it \def + \expandafter\let\expandafter\next\csname$[#1]\endcsname% $ this is the name we are trying to define + \ifx\next\relax % it is not defined yet + \setuprefs{#1}{\the\tempca}% + \else % already defined + \expandafter\ifx\csname$[#1]sym\endcsname\end % it i$ an existing explicit symbolic name, done + \else + \expandafter\ifx\csname$[#1]sym\endcsname\noindent % it i$ an existing implicit symbolic name of lhs, overwrite it + \setuprefs{#1}{\the\tempca}% + \else + \edef\next{\toksa{\space\space\noexpand\locksymname{#1}\harmlesscomment^^J}}\next + \edef\next{\toksb{\space\space\noexpand\unlocksymname{#1}\harmlesscomment^^J}}\next + \concat\setsncommands\toksa % symbolic name defined implicitly, disallow it + \concat\unsetsncommands\toksb + \fi + \fi + \fi + \advance\tempca\@ne +} + +\def\locksymname#1{\expandafter\let\csname$[#1]\endcsname\def} %$ +\def\unlocksymname#1{\expandafter\let\csname$[#1]\endcsname\relax} %$ + +\def\lhssymextra#1#2{% set the name of the left hand side implicitly + \expandafter\let\expandafter\next\csname$[#1]\endcsname%$ + \ifx\next\relax % not defined yet + \setuplhsref{#1}% + \setnameflag{#1}\noindent % this lhs name has been implicitly set + \fi % it is already defined +} + +\catcode`\^^A=\tempca + +% stack variable access + +\def\ym#1){% + \ifnum#1<\@ne + \putyyvalt + \else + \ifnum#1>\yyilen + \errmessage{parameter out of range (#1\space out of\space \the\yyilen)}% + \else + \expandafter\putyytoksx\csname$$'#1\endcsname + \fi + \fi +} + +\def\yn#1#{% + \ifnum#1<\@ne + \putyyval + \else + \ifnum#1>\yyilen + \errmessage{parameter out of range}% + \else + \expandafter\putyyassignment\csname$'\number#1\endcsname%$ + \fi + \fi +} + +\def\yx#1[{% + \expandafter\ifx\csname$[#1]\endcsname\yyval%$ + \putyyvalt + \else + \expandafter\ifx\csname$[#1]\endcsname\def%$ + \errmessage{reference to ambiguous symbolic name: #1}% + \else + \expandafter\putyytoksx\csname$$[#1]\endcsname + \fi + \fi +} + +\def\yz#1]{% + \expandafter\ifx\csname$[#1]\endcsname\yyval%$ + \putyyval + \else + \expandafter\ifx\csname$[#1]\endcsname\def%$ + \errmessage{reference to ambiguous symbolic name: #1}% + \else + \expandafter\putyyassignment\csname$[#1]\endcsname%$ + \fi + \fi +} + +\def\putyyval\else#1\fi\fi{% + \fi\yyvalx +} + +\def\yyvalx#1{% + \edef\next{\yyval{#1}}\next +} + +\def\putyyvalt\else#1\fi\fi{% + \fi\yyval +} + +\def\putyyassignment#1\fi\fi{% + \fi\fi\p@tyyassignment#1% +} + +\def\putyytoksx#1\fi\fi{% + \fi\fi#1% +} + +\def\p@tyyassignment#1#2{% + \yystringempty{#2}{#1}{#2\expandafter{#1}}% +} + +% natural order stack access macros + +\def\p@twwassignment#1#2{% + \edef\sts{\noexpand\p@@wwassignment{\expandafter\xdecrement\expandafter{\number#1}}}% + \expandafter\def\expandafter\sts\expandafter{\sts{#2}}% + \yyvsa\empty +} + +\def\p@@wwassignment#1#2#3{% + \ifnum#1=\z@ %we have got to the element we need + \yybreak{\yystringempty{#2}{#3}{#2{#3}}\let\sts\eatone}% + \else + \yybreak{\edef\sts{\noexpand\p@@wwassignment{\xdecrement{#1}}}% + \expandafter\def\expandafter\sts\expandafter{\sts{#2}}}% + \yycontinue +} + +\def\yy#1{% + \ifx#1[% + \yybreak{\yz}% + \else + \ifx#1]% + \yybreak@{\yx}% + \else + \ifx#1(% + \yybreak@@{\ym}% + \else + \yybreak@@{\yn#1}% + \fi + \fi + \yycontinue +} + +% a macro to access the value stack in direct order, i.e.\ from right to left +% no \yylen is necessary + +\def\bb#1#{% + \ifnum#1<\@ne + \yybreak{\putyyval}% + \else + \yybreak{\p@twwassignment{#1}}% + \yycontinue +} + +% symbolic name macros that prepare the environment for the use of the stack access macros above + +\def\setsymcs#1#2{% + \toksa{}\numberstochars#1\end + \toksb\expandafter{\csname$[\the\toksa]\endcsname}% $ + \toksc\expandafter{\csname$'#2\endcsname}% $ + \edef\next{\let\the\toksb\the\toksc}\next +} + +\def\setsymtr#1#2{% + \toksa{}\numberstochars#1\end + \toksb\expandafter{\csname$$[\the\toksa]\endcsname}% + \toksc\expandafter{\csname$$'#2\endcsname}% + \edef\next{\let\the\toksb\the\toksc}\next +} + +\def\setlhs#1{% + \toksa{}\numberstochars#1\end + \toksb\expandafter{\csname$[\the\toksa]\endcsname}% $ + \edef\next{\let\the\toksb\yyval}\next +} + +\def\setsym#1#2{% + \setsymcs{#1}{#2}% + \setsymtr{#1}{#2}% +} diff --git a/support/splint/tex/yynested.sty b/support/splint/tex/yynested.sty new file mode 100644 index 0000000000..db725abfc5 --- /dev/null +++ b/support/splint/tex/yynested.sty @@ -0,0 +1,85 @@ +% Copyright 2012-2015, 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/>. + +% nested and boundary parsing macros + +\newcount\boundarylower +\newcount\boundaryupper + +% for parsers that use short setup + +\boundaryupper-\@M +\boundarylower-\@M + +\expandafter\def\expandafter\parserdatainit\expandafter{% + \parserdatainit + \boundaryupper-\@M + \boundarylower-\@M +} + +% the next sequence is just a reminder of what would have to be done if +% reentrancy is required; the current state saving mechanism is intended for +% bare unoptimized parsers exclusively and does not handle any constant saving + +\expandafter\def\expandafter\savefullstateextra\expandafter{% + \savefullstateextra + % save \boundaryupper and \boundarylower +} + +\def\inputboundarynext#1{% + \yybytepure{ }\yycp@\boundarychar + #1\getstackpointer\yyvsa\relax + \yybyte\expandafter{\the\yybyte{#1}}% + \yyreturn % inserting something here will effectively insert it into the input stream +} + +\newcount\vspointer + +% to use while debugging, the sequence below displays the contents of the value stack + +\def\yyactione{% + \message{value stack at: \getstackpointer\yyvsa}% + \toksa\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter{\gettopofstackcs\yyvsa}% + \toksb\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter{\getmidstackcs\yyvsa{0}}% + \message{on the stack: \the\toksa, bottom: \the\toksb}% + \message{the value: \the\yyval}% + \message{rule: \the\yyn, length: \the\yylen}% +} + +% this is an example of boundary processing + +\def\yyaction{% + \vspointer=\getstackpointer\yyvsa\relax + \advance\vspointer-\yylen + \ifnum\vspointer<\boundarylower + \ifnum\boundaryupper>-\@M % all nested tokens will be reduced + \boundaryupper=-\@M + \boundarylower=-\@M + \message{reduction...(\the\vspointer: \the\yy(1).\the\yy(2).)}% + \printrule\yyn + \else % pre boundary tokens are getting reduced + \boundarylower=\vspointer + \advance\boundarylower\@ne + \fi + \else + \ifnum\vspointer<\boundaryupper % top nested tokens will be reduced + \boundaryupper=\vspointer + \fi + \fi + \yysymswitch{\yyn}% setting symbol names + \yybigswitch{\yyn}% + \yysymcleanup{\yyn}% removing symbol names from the namespace +} diff --git a/support/splint/tex/yyparse.sty b/support/splint/tex/yyparse.sty new file mode 100644 index 0000000000..ce5ab8b5e3 --- /dev/null +++ b/support/splint/tex/yyparse.sty @@ -0,0 +1,319 @@ +% Copyright 2012-2015, 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/>. + +% global variables: current token, state, variable to store various table indices + +\def\yyparse{% + \yylen=\z@ % + \yyinitstack\yyssa % state stack + \yyinitstack\yyvsa % data stack + \yystate=\z@ % + \yychar=\YYEMPTY\relax + \yylval{}% bogus value + \yynewstate +} + +\newif\iftracestacks +\newif\iftraceparserstates +\newif\iftracerules + +\def\yynewstate{% + \ifnum\yystate=\YYFINAL\relax + \yybreak\yypaccept + \else + \yypushr\yystate\on\yyssa + {% + \iftraceparserstates + \derrmessage{^^Jstate \the\yystate\iftracestacks, \fi}% + \fi + \iftracestacks + \iftraceparserstates + \else + \derrmessage{^^J}% + \fi + \showstack\yyssa\derrmessage{state stack: \stackcs^^J}% + \fi + }% + \yybreak\yybackup + \yycontinue +} + +\def\yybackup{% + \yyn=\fgetelemof{yypact}\at\yystate\relax + % yyn = yypact[yystate] + \ifnum\yyn=\YYPACTNINF\relax % if (yyn == YYPACT_NINF) (if(yypact_value_is_default(yyn))) + \yybreak\yydefault % goto yydefault + \else % else + \ifnum\yychar=\YYEMPTY\relax % if (yychar == YYEMPTY) + % ... ... if desired, this is where `hidden context' may be inserted + % ... ... for example: + % ... ... \gethidden\yychar + % ... ... \ifnum\yychar=\YYEMPTY\relax + % ... ... \yybreak@@\yylex + % ... ... \else + % ... ... \yybreak@@\yyparsetail + % ... ... \fi + % ... ... here \gethidden#1 is a hidden context-extracting macro that + % ... ... takes a token value from a special stream and puts it in #1 + % ... ... filling this special stream should be done by the lexer, + % ... ... respecting any state changes required. + \yybreak@\yylex % yychar = YYLEX + \else + \yybreak@\yyparsetail + \fi + \yycontinue +} + +\newif\iftracelookahead + +\def\yyparsetail{% this is where the lexer returns + \ifnum\yychar>\YYEOF\relax % if (yychar > YYEOF) + \yytoken=\fgetelemof{yytranslate}\at\yychar\relax + \iftracelookahead + \derrmessage{lookahead: \tokname, value: \the\yylval^^J}% + \fi + % yytoken = yytranslate[yychar] + \else % else + \yychar=\YYEOF\relax % yychar = yytoken = YYEOF + \yytoken=\YYEOF\relax + \fi% valid lookahead token + \advance\yyn by\yytoken % yyn = yypact[yystate] + yytoken + \ifnum\yyn<\z@ + \yybreak\yydefault + \else + \ifnum\yyn>\YYLAST\relax + \yybreak@\yydefault + \else + \ifnum\fgetelemof{yycheck}\at\yyn=\yytoken + % if (yyn >= 0 && yyn <= YYLAST && + % yytoken == yycheck[yyn]) + \yyn=\fgetelemof{yytable}\at\yyn\relax + % yyn = yytable[ yypact[yystate] + yytoken ] + \ifnum\yyn>\z@ % if (yyn > 0) ...shift + \iftraceactions + \derrmessage{shifting \tokname^^J}% + \fi + \yystate=\yyn % yystate = yytable[ yypact[yystate] + yytoken ] + \yychar=\YYEMPTY\relax + % yychar = YYEMPTY ...drop + % ...the + % ...shifted token + \yypushr\yylval\on\yyvsa + % ...shift the value + % *++yyvsa = yylval + \yybreak@@@\yynewstate % new state will be shifted + \else % ...if (yyn < 0) + \iffalse % if (yytable_value_is_error(yyn)) + % \ifnum\yyn=\YYTABLEERROR\relax + \yybreak@@@@\yyerr + \else + \yyn=-\yyn + \yybreak@@@@\yyreduce + \fi + \fi + \else + \yybreak@@\yydefault% goto yydefault + \fi + \fi + \yycontinue +} + +\newif\iftraceactions + +\def\yydefault{% + \yyn=\fgetelemof{yydefact}\at\yystate\relax + % yyn = yydefact[yystate] + \iftraceactions + \derrmessage{default action^^J}% + \fi + \ifnum\yyn=\z@ + \xskiptofi\yyerr + \else + \xskiptofi\yyreduce % if (yyn != 0) goto yyreduce + \fi +} + +\def\yyreduce{% + \yylen=\fgetelemof{yyrtwo}\at\yyn\relax + \iftracerules + \derrmessage{^^Jreducing (rule \the\yyn)}\printrule{\yyn}% + \fi + {% + \iftracestacks + \iftracerules + \else + \derrmessage{^^J}% + \fi + \showstack\yyssa + \derrmessage{stack: \stackcs^^Jpopping \the\yylen^^J}% + \fi + }% + \yyilen=\fgetelemof{yyrthree}\at\yyn\relax + \ifnum\yyilen>\z@ % this is an inline rule + \ifnum\yylen>\z@ + \errmessage{an inline rule with a nontrivial left hand side: rule \the\yyn}% + \fi + \else + \yyilen\yylen + \fi + \ifnum\yyilen>\z@ + \yypeekvstack\yyvsa\upto\yyilen + \yyval\csname $$'1\endcsname % $$ = $1 + \fi + % + \yyaction % value + % + \yypopstack\yyvsa\by\yylen + \yypopstack\yyssa\by\yylen % YYPOPSTACK(yylen) + \yypushr\yyval\on\yyvsa + % ...push the computed + % ...value on the value stack + % + \yyn=\fgetelemof{yyrone}\at\yyn\relax + % yyn = yyr1[yyn] + % + \yylen\yyn % + \advance\yylen-\YYNTOKENS\relax % ...reuse yylen + \yystate=\fgetelemof{yypgoto}\at\yylen\relax + % yystate = yypgoto[ yyn - YYNTOKENS ] + \yyreadstackr\yyssa\at\z@\to\yyilen % + % ...reuse yyilen + \advance\yystate\yyilen % yystate = yypgoto[ yyn - YYNTOKENS ] + yyssa[0] + % + \ifnum\yystate<\z@ % if (yystate < 0) + \yystate=\fgetelemof{yydefgoto}\at\yylen\relax + % yystate = yydefgoto[ yyn - YYNTOKENS ] + \else % else + \ifnum\yystate>\YYLAST\relax % ... + \yystate=\fgetelemof{yydefgoto}\at\yylen\relax + \else + \ifnum\fgetelemof{yycheck}\at\yystate=\yyilen + % if (yystate >= 0 && yystate <= YYLAST && yyssa[0] == yycheck[yystate]) + % + \yystate=\fgetelemof{yytable}\at\yystate\relax + % yystate = yytable[yystate] + \else + \yystate=\fgetelemof{yydefgoto}\at\yylen\relax + \fi + \fi + \fi + \yylen=\z@ + \yynewstate +} + +\newif\iftraceparseresults + +\def\yypaccept{% + \iftraceparseresults + \derrmessage{accepted^^J}% + \fi + \finishparse +} + +\def\yyerr{% + \iftraceparseresults + \derrmessage{(parse) error^^J}% + \fi + \cleanupparse +} + +% no symbolic name support by default + +\let\yysymswitch\eatone +\let\yysymcleanup\eatone + +\def\derrmessage#1{{% + \newlinechar=`\^^J% + \edef\tokname{\fgetelemof{yytname}\at\yytoken}% + \message{#1}% +}} + +% these macros reuse dedicated counters ... locally + +\def\printrule#1{{% some values are computed several times to save on register assignments + % this has more to do with not polluting the namespace than speed + \edef\ruleline{\space\space\space\fgetelemof{yytname}\at{\fgetelemof{yyrone}\at{#1}}:}% + \yyn=\fgetelemof{yyprhs}\at{#1} + \ifnum\fgetelemof{yyrhs}\at\yyn>\m@ne + \loop + \edef\ruleline{\ruleline\space\fgetelemof{yytname}\at{\fgetelemof{yyrhs}\at\yyn}}% + \advance\yyn\@ne + \ifnum\fgetelemof{yyrhs}\at\yyn>\m@ne + \repeat + \else + \edef\ruleline{\ruleline\space<empty>}% + \fi + \message{ -->\ruleline}% +}} + +% print the rule without using yyprhs and yyrhs (necessary if using +% bison version 3.0 or above) + +\def\printrule#1{{% + \edef\ruleline{\space\space\space\fgetelemof{yytname}\at{\fgetelemof{yyrone}\at{#1}}:}% + \ifnum\yylen>\z@ + \yypeeksstack\yyssa\upto\yylen\withprefix{\appendtoruleline}% + \else + \edef\ruleline{\ruleline\space<empty>}% + \fi + \message{ -->\ruleline}% +}} + +\def\appendtoruleline#1{% + \edef\ruleline{\ruleline\space\fgetelemof{yytname}\at{\fgetelemof{yystos}\at{#1}}}% +} + +% the two control sequences below are replaced in yyfaststack.sty +% to match the appropriate stack implementation + +\def\showstacksym#1{% + \edef\stackcs{\stackcs^^J \space\space\fgetelemof{yytname}\at{\fgetelemof{yystos}\at{#1}}}% +} + +\def\showstack#1{% + \def\stackcs{}% + \let\sts\showstacksym + #1% +} + +\newif\iftracediscardedinput + +\long\def\cleanupparse#1\endparse{% + \iftracediscardedinput + \immediate\write16{discarding the rest of the input}% + \fi + \yyerror +} + +\newif\ifyyparsefail + +\def\yyerror{\yyparsefailtrue} + +\long\def\finishparse#1\endparseinput{% + \yystringempty{#1}{}{\yylval{#1}\immediate\write16{skipping: \the\yylval}}% +} +\let\endparse\relax +\let\endparseinput\relax + +% action code + +\def\yyaction{% + \yysymswitch{\yyn}% setting symbol names + % the big switch, set \yyval + \yybigswitch{\yyn}% + % + \yysymcleanup{\yyn}% removing symbol names from the namespace +} diff --git a/support/splint/tex/yystype.sty b/support/splint/tex/yystype.sty new file mode 100644 index 0000000000..e37b298590 --- /dev/null +++ b/support/splint/tex/yystype.sty @@ -0,0 +1,65 @@ +% 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/>. + +% extra types for the bison scanner + +\def\lexspecialchar#1#2#3{\immediate\write16{encountered: \noexpand#1 fmark: #2, smark: #3}} + +\def\newlexerstateextra{% + \setnulstack{obstackforstring}% + \setnulstack{obstackforstringraw}% +} + +\def\savefullstateextra{% + \savestatelist{obstackforstring}% + \savestatelist{obstackforstringraw}% +} + +% lexer environment + +\def\yycomplain#1{\immediate\write16{#1}} % lexer errors +\def\yypdeprecated#1{\errmessage{option: #1 is ignored}} % outdated options + +\def\STRINGGROW{% + \concat\currentlaststring\yytextpure + \concat\currentlaststringraw\yytext} + +\def\STRINGFINISH{% + \laststring\currentlaststring + \laststringraw\currentlaststringraw + \yypushr\currentlaststring\on\obstackforstring + \yypushr\currentlaststringraw\on\obstackforstringraw + \currentlaststring{}% + \currentlaststringraw{}% +} +\def\STRINGFREE{% + \yypopstack\obstackforstring\by\@ne + \currentlaststring{}% + \yypopstack\obstackforstringraw\by\@ne + \currentlaststringraw{}% +} + +\def\bracketedidstr{} + +\newcount\contextstate % keeping track of the previous lexer state +\newcount\bracketedidcontextstate % similar but in the context of bracketed identifiers +\newcount\lonesting % nesting level for tags +\newcount\percentpercentcount + +\newtoks\laststring +\newtoks\laststringraw +\newtoks\currentlaststring +\newtoks\currentlaststringraw diff --git a/support/splint/tex/yytexlex.sty b/support/splint/tex/yytexlex.sty new file mode 100644 index 0000000000..a7e7dc3250 --- /dev/null +++ b/support/splint/tex/yytexlex.sty @@ -0,0 +1,1145 @@ +% Copyright 2012-2015, 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/>. + +% parsing \TeX\ input for pretty-printing; +% scanning and parsing are both done by using a low-level +% finite automaton; + +\def\yygetchar{% single buffered input + \ifyytextbackup + \yybyte\yytextseen + \yycp@\yytextseenlastchar + \yytextbackupfalse + \let\next\yyreturn + \else + \let\next\yyinput + \fi + \next +} + +% \TeX\ input + +\def\texdefaultstate{% +<>+-()^~!?*[]:.,`'\%\$\_ +\raw digit letter \raw +{% + \putother\yycp@\in\yybyte + \appendyybyte} += +{% + \appendr\texlinetoks{{}${}={}${}}% + \yygetchar +} +\{ +{% + \putother\yycp@\in\yybyte + \appendl\yybyte{\noexpand\bbal[\the\bbalance]}% + \advance\bbalance1\relax + \appendyybyte} +\} +{% + \putother\yycp@\in\yybyte + \advance\bbalance-1\relax + \appendl\yybyte{\noexpand\bbal[\the\bbalance]}% + \appendyybyte} +0123456789 +{% + \expandafter\ifcat\expandafter\noexpand\the\yybyte1% + \def\next{digit}% + \else + \def\next{^^A}% + \fi + \action\next\in\texdefaultstate +} +^^A % \yycp@==1 +{% + \edef\next{\noexpand\noexpand\the\yybyte}% + \action\next\in\texdefaultstate} +\raw\hbox\raw +{% + \appendnext} +\raw\end\raw +{% + \relax} +\raw\\ \_ \raw +{% + \appendyybyte} +\ \ +{% + \appendyybyte} +\\ +{% + \getcescape +} +/ +\raw escape \raw +{% + \let\currentstate\texcsname + \yygetchar} +}% + +\def\texcsname{% +<>+-()^~!?*\{\}[]:.,`'=\%\$\_/ +0123456789 +^^A +\ \ +\raw \end \\ \_ \ \raw +\raw escape \raw +{% + \let\currentstate\texdefaultstate + \putother\yycp@\in\yytext + \outputtexcs + \yygetchar} +% +\\ +{% + \getcescape +} +\raw letter \raw +{% + \let\currentstate\texcsnamelong + \yytext\yybyte + \yygetchar} +}% + +\def\texcsnamelong{% +<>+-()^~!?*\{\}[]:.,`'=\%\$\_\& +0123456789 +^^A +\ \ +\raw \end \\ \_ \raw +{% + \let\currentstate\texdefaultstate + \yytextseenlastchar=\yycp@ + \yytextseen=\yybyte + \yytextbackuptrue + \outputtexcs + \yygetchar} +\\ +{% + \getcescape +} +/ +\raw escape \raw +{% + \let\currentstate\texcsname + \outputtexcs + \yygetchar} +\raw letter \raw +{% + \concat\yytext\yybyte + \yygetchar} +}% + +\def\texcescape{% +\\ +{% + \let\currentstate\esccurrentstate + \yycp@=`\\% + \putother\yycp@\in\yybyte + \def\next{escape}% + \action\next\in\currentstate} +} + +\def\texescdefault{% + \let\currentstate\esccurrentstate + \yycp@=`\ % + \yybyte{\ }% + \action\yycp@\in\currentstate +} + +\def\getcescape{% + \let\esccurrentstate\currentstate + \let\currentstate\texcescape + \let\default\texescdefault + \yygetchar +} + +\setspecialcharsfrom\texdefaultstate +\setspecialcharsfrom\texcsname +\setspecialcharsfrom\texcsnamelong +\setspecialcharsfrom\texcescape + +\newtoks\texlinetoks % parsed \TeX\ tokens +\newtoks\texidxtoks % indexing commands + +\def\texlexer{% + \let\default\yygetchar + \let\next\yycp@ + \ifnum\yycp@>"20 % + \ifnum\yycp@<"7F % a character + \expandafter\ifcat\expandafter\noexpand\the\yybyte a% + % this test allows one some control over what constitutes a control + % sequence name (by saying, for example, \let\$a or manipulating \catcodes) + % this is bordering on a bug + \def\next{letter}% + \fi + \fi + \fi + \action\next\in\currentstate +} + +\def\outputtexcs{% + \expandafter\ifx\csname\the\yytext\defTpostfix\endcsname\relax + \putother{`\\}\in\toksa + \concat\texlinetoks\toksa + \concat\texlinetoks\yytext + \appendr\texlinetoks{\noexpand\hbox{$\noexpand\,$}}% + \else + \appendr\texlinetoks{\expandafter\expandafter\expandafter\noexpand\expandafter\csname\the\yytext xTeXmode\endcsname}% + \fi + \appendr\texidxtoks{% + \termindex{{\nx\nx\nx\texcsstring{\expandafter\charstonumberse\the\yytext\end}}{\texnspace}{\nx\the\pageno}{\secno}}% + }% +} + +% the `calling conventions' for indexing \TeX\ control sequences are too different to use canned indexing macros +% (the second parameter is a register so it has to be expanded before the \charstonumberse processes it) +% we therefore invoke the macros by hand + +\def\texidxdomain{T} + +\def\texcsidxrank{2} + +\def\writetexidxentry#1{\iftermindex\write\gindex{\nx\nx\expandafter\nx\csname\texidxdomain TI\endcsname\texcsidxrank#1}\fi} + +\def\appendyybyte{\concat\texlinetoks\yybyte\yygetchar} +\def\appendnext#1{\toksa{#1}\concat\texlinetoks\toksa\yygetchar} + +\def\defTpostfix{xTeXmode} + +\def\stripyybyte{% + \expandafter\stripyyb@te\the\yybyte +} + +\def\stripyyb@te#1#2{\noexpand#2} + +% TODO: +% the macros below are in their present shape due to the forces of `historical evolution': +% \TeX\ pretty printing needs to be completely rewritten, however, the existing macros +% do a passable job so they remain in this rather random shape. +% the items below need more urgent attention: +% +% o introduce TeXn_ that take a number and a string argument + +\newcount\bbalance +\newif\iftracetexpp +\newtoks\textoks + +\def\TeXx(#1)#2;{% TODO + \let\oldttdot\.\relaxcweb + \textoks{}\let\.\dotcollect + #1% + \restorecweb\let\.\oldttdot + \expandafter\T@Xx\the\textoks} + +\def\mypar{\par} + +\def\TeXb(#1)#2;{% TeX material begin + {}$% + \let\oldsix\6% + \let\6\ignorespaces + \let\oldC\C + \let\C\saveCcomments + \let\oldttdot\.\relaxcweb + \textoks{}\toksa{}\let\.\dotcollectb + #1% + \restorecweb\let\.\oldttdot + \dotcollectstripquotes + ${}} + +\def\TeXa(#1)#2;{% TeX material add + {}$% + \let\oldttdot\.\relaxcweb + \toksa{}\let\.\dotcollectb + #1% + \restorecweb\let\.\oldttdot + \dotcollectstripquotes + ${}} + +\def\TeXf(#1)#2;{% TeX material add + {}$% + \let\oldttdot\.\relaxcweb + \toksa{}\let\.\dotcollectb + \textoks\expandafter{\the\textoks\hbox{\6}}% + #1% + \restorecweb\let\.\oldttdot + \dotcollectstripquotes + ${}} + +\def\TeXo(#1)#2;{% TeX material output + \let\oldttdot\.\relaxcweb + \let\.\dotcollect + \let\6\oldsix + \let\C\oldC + #1% + \restorecweb\let\.\oldttdot + $\expandafter\T@Xx\expandafter"\the\textoks"$} + +\def\TeXao(#1)#2;{% TeX material output + {}$\let\oldttdot\.\relaxcweb + \toksa{}\let\.\dotcollectb + \let\6\oldsix + \let\C\oldC + #1% + \restorecweb\let\.\oldttdot + \dotcollectstripquotes + $\expandafter\T@Xx\expandafter"\the\textoks"${}${}} + +\def\TeXfo(#1)#2;{% TeX material output + {}$\let\oldttdot\.\relaxcweb + \toksa{}\let\.\dotcollectb + \textoks\expandafter{\the\textoks\hbox{\6}}% + \let\6\oldsix + \let\C\oldC + #1% + \restorecweb\let\.\oldttdot + \dotcollectstripquotes + $\expandafter\T@Xx\expandafter"\the\textoks"${}${}} + +\let\TeXxi\TeXx +\def\inlineTeXx#1{$\TeXxi(\.{"#1"});$} % for indexing macros + +\def\dotcollect#1{\toksa{#1}\concat\textoks\toksa} +\def\dotcollectb#1{\toksb{#1}\concat\toksa\toksb} +\def\dotcollectstripquotes{\expandafter\d@tcollectstripquotes\the\toksa} +\def\d@tcollectstripquotes"#1"{\toksa{#1}\concat\textoks\toksa} +\def\saveCcomments#1{\toksc{\hbox{\oldC{#1}}}\concat\textoks\toksc} +\def\relaxcweb{\savehcs{local-namespace}{\)}} +\def\restorecweb{\restorecs{local-namespace}{\)}} + +\def\T@Xx"#1"{% + {}${}%$ + \iffalse{\fi % alignment! + \begingroup + % tune up the standard input routines + \let\yyreturn\texlexer + \let\multicharswitch\empty + \let\onecharswitch\empty + \setspecialcharsfrom\multicharswitch % debugging + \setspecialcharsfrom\onecharswitch + % + \let\currentstate\texdefaultstate + \texlinetoks{}\texidxtoks{}\bbalance\z@ + \let\bbal\bbalempty + \yytextbackupfalse + \restorecsxlist\texnspace\alltexsymbols + \let\termindex\writetexidxentry + \yygetchar#1\end + \toksc{#1}% + \iftracetexpp{\newlinechar=`^^J% + \errmessage{TeX_ input: \the\toksc^^JTeX_ first pass: \the\texlinetoks}}\fi + \ifnum\bbalance=\z@ + \else + \bbbalance + \fi + \iftracetexpp\errmessage{TeX_ final pass: \the\texlinetoks}\fi + \concat\texlinetoks\texidxtoks + \expandafter + \endgroup + \expandafter + \begingroup +% the actual typesetting must happen outside the group +% otherwise there is a risk that an output routine is called before +% the group is complete and \yyreturn definition is wrong so \yyparse +% will not be able to function + \expandafter\texlinetoks\expandafter{\the\texlinetoks}% + \let\bbal\bbalempty\bbalance\z@ + \restorecsxlist\texnspace\alltexsymbols + \let\termindex\writetexidxentry\tt\chardef\_=`\_\the\texlinetoks + \endgroup + \iffalse}\fi + {}${}%$ +} + +\def\alltexsymbols{% + \space\toksa\toksb\toksc\tokse\toksf\the\ifx\ifnum\fi\else + \def\edef\let\empty\next\switchon\in\concat\appendr\default + \noexpand\emptyterm\print\relax\yy\inmath\omit\hfil\getfirst + \getsecond\getthird\getfourth\getfifth\nx\to\hspace\toksd\rhscont + \rhscnct\rhsbool\table\ifrhsfull\rhsfulltrue\rhsfullfalse + \yyval\tempca\tempcb\z@\@ne\tw@\m@ne\advance\ifcat\iftracebadchars + \bb\yylexreturnptr\yylexreturn\yylexreturnval\yylexreturnchar + \yylexreturntext\yylexnext +} + +\def\collectspaces#1{% + \def\next{#1}% + \ifx#1\endcontainer + \let\next\relax + \else + \ifx\next\spacecontainer + \appendr\toksa\next + \let\next\collectspaces + \else + \let\next\eattoend + \fi + \fi + \next +} + +\def\spacecontainer{\ } + +\def\texnspace{texline} + +\let\defpostfix\defTpostfix +\let\defprefix\empty + +\let\defypreamble\empty % for indexing macros +\def\defypostamble{ {\rm(\.{\\\thisnamex})}} + +\let\settgroup\relax + +\defx\space{\hbox{$\,$\char`\ $\,$}}{texline} + +\defx\hspace{\hbox{$\,$\char`\ $\,$}}{texline} + +\defy\hspace{\hbox{$\,$\char`\ $\,$}}{index} + +\defx\advance{% + $\mathop{\hbox{\bf add}}{}$% +}{texline} + +\defy\advance{% + {\bf add}% +}{index} + +\defx\z@{% + $\,0_{\rm R}\,$% +}{texline} + +\defy\z@{% + $0_{\rm R}$% +}{index} + +\defx\@ne{% + $\,1_{\rm R}\,$% +}{texline} + +\defy\@ne{% + $1_{\rm R}$% +}{index} + +\defx\tw@{% + $\,2_{\rm R}\,$% +}{texline} + +\defy\tw@{% + $2_{\rm R}$% +}{index} + +\defx\m@ne{% + $\,-1_{\rm R}\,$% +}{texline} + +\defy\m@ne{% + $-1_{\rm R}$% +}{index} + +\defx\tempca{% + ${}t_a{}$% +}{texline} + +\defy\tempca{% + $t_a$% +}{index} + +\defx\tempcb{% + ${}t_b{}$% +}{texline} + +\defy\tempcb{% + $t_b$% +}{index} + +\defx\toksa{% + {}${}v_a{}${}% + \def\setegroup{}% + \def\setpgroup{% + $\leftarrow\langle\,\hbox{\the\toksa}% + \if\next]% + \else + \rangle% + \fi + $}\grabbalanced +}{texline} + +\defy\toksa{% + ${}v_a{}$% +}{index} + +\defx\toksb{% + {}${}v_b{}${}% + \def\setegroup{}% + \def\setpgroup{% + $\leftarrow\langle\,\hbox{\the\toksa}% + \if\next]% + \else + \rangle% + \fi + $}\grabbalanced +}{texline} + +\defy\toksb{% + ${}v_b{}$% +}{index} + +\defx\toksc{% + {}${}v_c{}${}% + \def\setegroup{}% + \def\setpgroup{% + $\leftarrow\langle\,\hbox{\the\toksa}% + \if\next]% + \else + \rangle% + \fi + $}\grabbalanced +}{texline} + +\defy\toksc{% + ${}v_c{}$% +}{index} + +\defx\toksd{% + {}${}v_d{}${}% + \def\setegroup{}% + \def\setpgroup{% + $\leftarrow\langle\,\hbox{\the\toksa}% + \if\next]% + \else + \rangle% + \fi + $}\grabbalanced +}{texline} + +\defy\toksd{% + ${}v_d{}$% +}{index} + +\defx\tokse{% + {}${}v_e{}${}% + \def\setegroup{}% + \def\setpgroup{% + $\leftarrow\langle\,\hbox{\the\toksa}% + \if\next]% + \else + \rangle% + \fi + $}\grabbalanced +}{texline} + +\defy\tokse{% + ${}v_e{}$% +}{index} + +\defx\toksf{% + {}${}v_f{}${}% + \def\setegroup{}% + \def\setpgroup{% + $\leftarrow\langle\,\hbox{\the\toksa}% + \if\next]% + \else + \rangle% + \fi + $}\grabbalanced +}{texline} + +\defy\toksf{$v_f$}{index} + +\defx\yyval{% + {}${}\Upsilon{}${}% + \def\setegroup{}% + \def\setpgroup{% + $\leftarrow\langle\,\the\toksa + \if\next]% + \else + \rangle% + \fi + $}\grabbalanced +}{texline} + +\defy\yyval{% + ${}\Upsilon{}$% +}{index} + +\def\setflexreturn#1{% + \def\setegroup{{\bf return}#1}% + \def\setpgroup{% + {% + \let\texidxdomain\bisonidxdomain + \tokse\toksa + \expandafter\nameproc\expandafter{\the\toksa}% + \ifyyparsefail + \edef\next{\toksa{\termmetastyle{% + \expandafter\gidxentry\expandafter{\expandafter\termvstring\expandafter}\expandafter{\the\toksa}% + \let\nx\idxfont\nx\empty\nx\tt\the\toksa\nx\/% + }}}\next + \else + \expandafter\settermstyle\expandafter{\the\tokse}% + \fi + {}$\mathop{\hbox{{\bf return}#1}}\hbox{\the\toksa}${}}% + }\grabbalanced +} + +\defx\yylexreturnptr{% + \setflexreturn{$_p${}}% +}{texline} + +\defy\yylexreturnptr{% + {\bf return$_p$}% +}{index} + +\defx\yylexreturnchar{% + {\bf return$_c$}% +}{texline} + +\defy\yylexreturnchar{% + {\bf return$_c$}% +}{index} + +\defx\yylexnext{% + {\bf continue}% +}{texline} + +\defy\yylexnext{% + {\bf continue}% +}{index} + +\defx\yylexreturn{% + \setflexreturn{$_l${}}% +}{texline} + +\defy\yylexreturn{% + {\bf return$_l$}% +}{index} + +\defx\yylexreturnval{% + \setflexreturn{$_v${}}% +}{texline} + +\defy\yylexreturnval{% + {\bf return$_v$}% +}{index} + +\defx\yylexreturntext{% + {\bf return$_t$}% +}{texline} + +\defy\yylexreturntext{% + {\bf return$_t$}% +}{index} + +\defx\table{{}${}\Omega{}${}}{texline} + +\defy\table{$\Omega$}{index} + +\defx\relax{\hbox{$\circ$}}{texline} + +\defy\relax{\hbox{$\circ$}}{index} + +\defx\the#1{% + \toksa{#1}% + \let\prevdefault\default + \def\default{\let\default\prevdefault{}$\mathop{\rm val}\,${}#1}% + \taction{\the\toksa}\in\thecomaction +}{texline} + +\defy\the{% + $\mathop{\rm val}\cdot$ {\rm or }% + \lcenclose{$\cdot$}% +}{index} + +\def\thecomaction{% +\raw \toksaxTeXmode\toksbxTeXmode\tokscxTeXmode\toksdxTeXmode\toksexTeXmode\toksfxTeXmode \raw +{% + \let\default\prevdefault + \lcenclose{\the\toksa}% +}% +} + +\setspecialcharsfrom\thecomaction + +\def\lcenclose#1{% + {}$\llcorner\hbox{#1}\lrcorner${}% +} + +\defx\inmath{% + {}$^\bullet${}% + \def\setegroup{}% + \def\setpgroup{% + $(\,\hbox{\the\toksa}% + \if\next]% + \else + )% + \fi + $}\grabbalanced +}{texline} + +\defy\inmath{% + $^\bullet(\,\cdot\,)$% +}{index} + +\defx\ifx{% + {\bf if$_{\rm x}\;$}% +}{texline} + +\defy\ifx{% + {\bf if$_{\rm x}$}% +}{index} + +\defx\ifnum{% + {\bf if$_\omega\;$}% +}{texline} + +\defy\ifnum{% + {\bf if$_\omega$}% +}{index} + +\defx\ifcat{% + {\bf if$_{\rm cat}\;$}% +}{texline} + +\defy\ifcat{% + {\bf if$_{\rm cat}$}% +}{index} + +\defx\iftracebadchars{% + {\bf if$_t$ {\rm[{\tt bad char}]}$\;$}% +}{texline} + +\defy\iftracebadchars{% + {\bf if$_t$ {\rm[{\tt bad char}]}}% +}{index} + +\defx\else{% + {\bf else$\;$}% +}{texline} + +\defx\fi{% + {\bf fi$\;$}% +}{texline} + +\defx\def{% + {\bf def$\;$}% +}{texline} + +\defy\def{% + {\bf def}% +}{index} + +\defx\edef{% + {\bf def$_{\rm x}\;$}% +}{texline} + +\defy\edef{% + {\bf def$_{\rm x}$}% +}{index} + +\defx\let{% + {\bf let$\;$}% +}{texline} + +\defx\next{% + {\bf next$\;$}% +}{texline} + +\defx\empty{% + $\emptyset$% +}{texline} + +\defy\empty{% + $\emptyset$% +}{index} + +\defx\ifrhsfull{% + {\bf if {\rm ($\,$rhs${}={}$full$\,$)}$\;$}% +}{texline} + +\defy\ifrhsfull{% + {\bf if {\rm ($\,$rhs${}={}$full$\,$)}}% +}{index} + +\defx\rhsfulltrue{% + {\rm rhs${}={}$full$\,$}% +}{texline} + +\defy\rhsfulltrue{% + {\rm rhs${}={}$full}% +}{index} + +\defx\rhsfullfalse{% + {\rm rhs${}={}$not full$\,$}% +}{texline} + +\defy\rhsfullfalse{% + {\rm rhs${}={}$not full}% +}{index} + +\defx\noexpand{% + $^{\rm nox}$% +}{texline} + +\defx\nx{% + $^{\rm nx}$% +}{texline} + +\defy\noexpand{% + $^{\rm nox}$% +}{index} + +\defy\nx{% + $^{\rm nx}$% +}{index} + +\defx\to{% + ${}\mapsto{}$% +}{texline} + +\defx\emptyterm{% + \hbox{$\ulcorner\ldots\urcorner$}% +}{texline} + +\defy\emptyterm{% + \hbox{$\ulcorner\ldots\urcorner$}% +}{index} + +\defx\hfil{\hbox{$\,\Leftrightarrow\,$}}{texline} +\defx\omit{\hbox{$\,{\times\atop\times}$}}{texline} + +\defx\yy#1{% + \if\noexpand#1]% + \let\next\seeksymtt + \else + \if\noexpand#1[% + \let\next\seeksymts + \else + \if\noexpand#1(% + \let\next\seeknott + \else + \def\next{\seeknots#1}% + \fi + \fi + \fi + \next +}{texline} + +\defy\yy{% + $\Upsilon\kern-1pt{}_{\rm?}$% +}{index} + +\def\seeknots#1\bbal{% + \let\setegroup\relax + \ifnum#1>0\relax + \def\setpgroup{% + \edef\next{\the\toksa}% + \ifx\next\empty + $\Upsilon\kern-1pt{}_{\number\tempca}$% + \else + $\Upsilon\kern-1pt{}_{\number\tempca}\rightarrow[{}${\tt\the\toksa}]$\;$% + \fi}% + \else + \def\setpgroup{% + $\Upsilon\leftarrow\langle{}${\tt\the\toksa}%${}% + \if\next]% + \else + $\rangle\;$% + \fi}% + \fi + \tempca#1\relax\printtermt +} + +\def\seeksymts#1]{% + \let\setegroup\relax + \def\setpgroup{$\Upsilon\kern-1pt{}_{\rm#1}\langle{}${\tt\the\toksa}${}\rangle\;$}\grabbalanced +} + +\def\seeksymtt#1[{{$\Upsilon\kern-1pt{}_{\rm#1}$}} + +\def\seeknott#1){{$\Upsilon\kern-1pt{}_{\rm#1}$}} + +\def\printtermt{\grabbalanced\bbal} + +\defx\print{% + \hbox{\it print$\;$}% + \def\setpgroup{{\tt"}\the\toksa{\tt"}$\,$}% + \def\setegroup{}% + \grabbalanced +}{texline} + +\defx\bb#1\bbal{% + \let\setegroup\relax + \ifnum#1>0\relax + \def\setpgroup{% + \edef\next{\the\toksa}% + \ifx\next\empty + ${}_{\number\tempca}\kern-1.5pt\Upsilon$% + \else + ${}_{\number\tempca}\kern-1.5pt\Upsilon\rightarrow[{}${\tt\the\toksa}$]\;$% + \fi}% + \else + \def\setpgroup{% + $\Upsilon\leftarrow\langle{}${\tt\the\toksa}%${}% + \if\next]% + \else + $\rangle\;$% + \fi}% + \fi + \tempca#1\relax\printtermt +}{texline} + +\defy\bb{% + ${}_{\rm?}\kern-2pt\Upsilon$% +}{index} + +\defx\switchon{% + \hbox{\bf switch$\;$}% + \def\setpgroup{{$($}\the\toksa{$)$}$\,$}% + \def\setegroup{}% + \grabbalanced +}{texline} + +\defy\switchon{% + \hbox{\bf switch$\;$}% +}{index} + +\defx\in{% + $\,\varepsilon\,$% +}{texline} + +\defy\in{% + $\,\varepsilon\,$% +}{index} + +\defx\concat#1#2{% + \hbox{#1${}\leftarrow{}$#1${}+_{\rm s}{}$#2$\;$}% +}{texline} + +\defy\concat{% + \hbox{$A\leftarrow A+_{\rm s}B$}% +}{index} + +\defx\appendr#1{% + \hbox{#1${}\leftarrow{}$#1${}+_{\rm sx}{}$}% + \def\setpgroup{{$[\,$}\the\toksa{$\,]$}$\,$}% + \def\setegroup{}% + \grabbalanced +}{texline} + +\defy\appendr{% + \hbox{$A\leftarrow A+_{\rm sx}B$}% +}{index} + +\defx\default{% + {\tt default}$\;$% +}{texline} + + +\defx\getfirst{% + {}${}\pi_1${}% + \def\setegroup{\relax}% + \def\setpgroup{% + ${}(\hbox{\the\toksa}% + \if\next]% + \else + )% + \fi + $}\grabbalanced +}{texline} + +\defy\getfirst{% + ${}\pi_1$% +}{index} + +\defx\getsecond{% + {}${}\pi_2${}% + \def\setegroup{\relax}% + \def\setpgroup{% + ${}(\hbox{\the\toksa}% + \if\next]% + \else + )% + \fi + $}\grabbalanced +}{texline} + +\defy\getsecond{% + ${}\pi_2$% +}{index} + +\defx\getthird{% + {}${}\pi_3${}% + \def\setegroup{\relax}% + \def\setpgroup{% + ${}(\hbox{\the\toksa}% + \if\next]% + \else + )% + \fi + $}\grabbalanced +}{texline} + +\defy\getthird{% + ${}\pi_3$% +}{index} + +\defx\getfourth{% + {}${}\pi_4${}% + \def\setegroup{\relax}% + \def\setpgroup{% + ${}(\hbox{\the\toksa}% + \if\next]% + \else + )% + \fi + $}\grabbalanced +}{texline} + +\defy\getfourth{% + ${}\pi_4$% +}{index} + +\defx\getfifth{% + {}${}\pi_5${}% + \def\setegroup{\relax}% + \def\setpgroup{% + ${}(\hbox{\the\toksa}% + \if\next]% + \else + )% + \fi + $}\grabbalanced +}{texline} + +\defy\getfifth{% + ${}\pi_5$% +}{index} + +\defx\rhscont{% + {}${}\pi_{\{\}}${}% + \def\setegroup{\relax}% + \def\setpgroup{% + ${}(\hbox{\the\toksa}% + \if\next]% + \else + )% + \fi + $}\grabbalanced +}{texline} + +\defy\rhscont{% + ${}\pi_{\{\}}$% +}{index} + +\defx\rhscnct{% + {}${}\pi_{\leftrightarrow}${}% + \def\setegroup{\relax}% + \def\setpgroup{% + ${}(\hbox{\the\toksa}% + \if\next]% + \else + )% + \fi + $}\grabbalanced +}{texline} + +\defy\rhscnct{% + ${}\pi_{\leftrightarrow}$% +}{index} + +\defx\rhsbool{% + {}${}\pi_{\vdash}${}% + \def\setegroup{\relax}% + \def\setpgroup{% + ${}(\hbox{\the\toksa}% + \if\next]% + \else + )% + \fi + $}\grabbalanced +}{texline} + +\defy\rhsbool{% + ${}\pi_{\vdash}$% +}{index} + +\def\bbalempty[#1]#2{% + \ifx#2]\relax + \else + \ifx#2[\relax + \else + \ifnum`#2=`\{% + #2\hbox{$\,$}% + \else + \unskip\hbox{$\,$}#2% + \fi + \fi + \fi +}% + +\def\bbbalance{% + \ifnum\bbalance>0 + \loop + \advance\bbalance-1\relax + \appendr\texlinetoks{\noexpand\bbal[\the\bbalance]]}% + \ifnum\bbalance>0 + \repeat + \else + \tempca-\bbalance + \toksd{}% + \loop + \advance\tempca-1\relax + \appendl\toksd{\noexpand\bbal[\the\tempca][}% + \ifnum\tempca>0 + \repeat + \tempca-\bbalance + \bbalance\tempca + \texlinetoks{}\texidxtoks{}% + \expandafter\yygetchar\the\toksc\end +% \errmessage{\the\texlinetoks...\the\toksd...\the\bbalance}% + \appendl\texlinetoks{\the\toksd}% + \fi +} + +\def\grabbalanced{% + \futurelet\next\gr@bbalanced +} + +\def\gr@bbalanced{% + \ifx\next\bbal + \let\next\gr@bb@lanced + \else + \let\next\settgroup + \fi + \next +} + +\def\gr@bb@lanced\bbal[#1]#2{% + \ifnum`#2=`\}% this is a closing parenthesis we are inside a group + \def\next{\setegroup\bbal[#1]#2}% + \toksa{#2}% + \else + \ifnum`#2=`]% + \def\next{\setegroup\bbal[#1]#2}% + \toksa{#2}% + \else + \def\next##1\bbal[#1]##2{% + \toksa{##1}\let\next##2% + \setpgroup + }% + \fi + \fi + \next +} diff --git a/support/splint/tex/yyunion.sty b/support/splint/tex/yyunion.sty new file mode 100644 index 0000000000..d9749a86b9 --- /dev/null +++ b/support/splint/tex/yyunion.sty @@ -0,0 +1,1523 @@ +% Copyright 2012-2015, 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/>. + +% prototypes of all the macros produced by the parser +% we will follow the convention: 12string is a string of category 12 characters and spaces, tex_string: a string +% of TeX tokens; sptr is a pointer to the stash stream, fptr is a pointer to the format stream + +\def\yyuniontag{\yyunion} +\def\parserstrictnamespace{parser-strict} +\def\parserprototypesnamespace{parser-strict:headers} + +\def\yyunion{\currentyyunionnamespace} +\def\currentyyunionnamespace{generic} + +% types inserted by the input routines: these should not be tampered with randomly +% therefore they are not included in the yyunion list and only defined once below and redefined later +% permanently + +% insidemost + +\long\def\stashed#1{} % stashed material (usually \Cee\ code) :: \stashed{tex_string} +\long\def\sflush#1#2{} % stash flushing marker :: \sflush{tex_string} +\def\format#1{} % format material triggered by braces and the start of production :: \format{tex_string} +\def\formatlocal#1{} % format material triggered by every term :: \formatlocal{tex_string} + +% level 1 + +\long\def\strm[#1]#2.[#3]{} % a stream element :: \strm[digits]{\stashed|\format|\formatlocal}.[digits] + +% types returned by the lexer (* marks the types that get removed by the parser in some cases) + +\def\midf#1#2{} % rule separator :: \midf{fptr}{sptr} +\defp\stringify#1#2#3#4{} % STRING :: \stringify{12string}{tex_string}{fptr}{sptr} +\defp\idit#1#2#3#4{} % ID :: \idit{12string}{tex_string}{fptr}{sptr} +\defp\tagit#1#2#3#4{} % TAG :: \tagit{12string}{tex_string}{fptr}{sptr} +\defp\charit#1#2#3#4{} % CHAR :: \charit{12string}{tex_string}{fptr}{sptr} +\defp\anint#1#2#3{} % INT :: \anint{digits}{fptr}{sptr} +\defp\hexint#1#2#3{} % INT :: \hexint{0[xX][0-9A-F]+}{fptr}{sptr} +\defp\braceit#1#2#3{} % *BRACED_CODE :: \braceit{tex_string}{fptr}{sptr} +\defp\preckind#1#2#3{} % *precedence operator :: \preckind{12string}{fptr}{sptr} +\defp\flexoptionpair#1#2{} % a flex option :: \flexoptoinpair{\idit}{\idit|\stringify} + +% types inserted by the parser + +% insidemost + +\defp\termname#1#2{} % a production term :: \termname{\idit|\stringify|\charit}{\idit} +\defp\mergeop#1#2#3{} % merge directive :: \mergeop{\tagit}{fptr}{sptr} +\defp\dprecop#1#2#3{} % dprec directive :: \dprecop{\anint|\hexint}{fptr}{sptr} +\defp\sprecop#1#2#3{} % prec directive :: \sprecop{\idit|\stringify|\charit}{fptr}{sptr} +\defp\rrhssep#1#2{} % :: \rrhssep{fptr}{sptr} +\defp\arhssep#1#2{} % :: \arhssep{fptr}{sptr} +\defp\rarhssep#1#2{} % :: \rarhssep{fptr}{sptr} +\defp\hspace#1#2{} % a space has to take two parameters just like any connector :: \hspace{fptr}{sptr} +\defp\emptyterm{} +\defp\onesymbol#1#2#3{} % a symbol definition :: \onesymbol{\idit}{\anint|\hexint}{\stringify} +\defp\bracedvalue#1#2#3{} % a braced variable value :: \bracedvalue{tex_string}{fptr}{sptr} + +%level 1 + +\defp\rhs#1#2#3{} % a `right-hand side' :: \rhs{[\termname\hspace\rarhssep\arhssep\actbraces]+}{\arhssep|<nothing>}{\ifrhsfull} +\defp\actbraces#1#2#3#4#5\bdend{} % action braces :: \actbraces{tex_string}{\idit|<nothing>}{fptr}{sptr}directive*\bdend +\defp\bpredicate#1#2#3#4#5\bdend{} % predicate :: \bpredicate{tex_string}{<nothing>}{fptr}{sptr}directive*\bdend + +% level 2 + +\defp\prodheader#1#2#3#4{} % a `left-hand side' of a production :: \prodheader{\idit}{\idit}{fptr}{sptr} +\defp\rules#1#2#3{} % a complete right-hand side :: \rules{[\rhs|\rrhssep]}{max fptr}{max sptr} +\defp\symbolprec#1#2{} % symbol precedence :: \symbolprec{\idit|\stringify|\charit}{\anint|\hexint} +%\def\pcluster#1#2{} % a production cluster :: \pcluster{\prodheader}{\termname|...} should never appear in the final output + +% level 3 + +\defp\oneproduction#1#2#3{} % a complete production :: \oneproduction{\prodheader\rules}{fptr}{sptr} +\defp\prodprodsepsmall{} % production separator +\defp\prodprodsep{} % production separator +\defp\prodprodseplarge{} % production separator +\defp\optoptsepsmall{} % separator between options +\defp\posmark#1#2{} % the position marker :: \posmark{fptr}{sptr} +\defp\tokendecls#1#2#3{} % token declarations :: \tokendecls{[\onesymbol]+}{fptr}{sptr} +\defp\ntermdecls#1#2#3{} % nterm declarations :: \ntermdecls{[\onesymbol]+}{fptr}{sptr} +\defp\typedecls#1#2#3#4{} % type declarations :: \typedecls{\tagit}{[\idit\stringify\charit]+}{fptr}{sptr} +\defp\precdecls#1#2#3#4#5{} % precedence declarations :: \precdecls{left|right|nonassoc|precedence}{\tagit}{[\idit\stringify\charit]+}{fptr}{sptr} +\defp\flexsstatedecls#1#2#3{} % flex state declarations (nonexlusive) :: \flexsstatedecls{[\idit\stringify]+}{fptr}{sptr} +\defp\flexxstatedecls#1#2#3{} % flex state declarations (exclusive) :: \flexxstatedecls{[\idit\stringify]+}{fptr}{sptr} +\defp\flexoptiondecls#1#2#3{} % flex state declarations :: \flexoptiondecls{[\flexoptionpair]+}{fptr}{sptr} +\defp\oneparametricoption#1#2#3#4{} % option :: \oneparametricoption{option-name}{\stringify|\idit}{fptr}{sptr} +\defp\optionflag#1#2#3#4{} % option flag :: \optionflag{flag name}{abbreviated name}{fptr}{sptr} +\defp\paramdef#1#2#3#4{} % parameters :: \paramdef{\braceit}{parameter domain}{fptr}{sptr} +\defp\codepropstype#1#2#3#4#5#6#7{} % term method :: \codepropstype{printer|destructor}{tex_string}{\stringit|\idit}{fptr}{sptr}{fptr}{sptr} +\defp\initaction#1#2#3{} % initial action :: \initaction{tex_string}{fptr}{sptr} +\defp\codeassoc#1#2#3#4#5#6#7{} % code association :: \codeassoc{code kind}{|\idit}{tex_string}{fptr}{sptr}{fptr}{sptr} +\defp\vardef#1#2#3#4{} % variable definition :: \vardef{\idit|\stringify}{|\idit|\stringify|\bracedvalue}{fptr}{sptr} +\defp\prologuecode#1#2#3#4#5{} % prologue code :: \prologuecode{tex_string}{fptr}{sptr}{fptr}{sptr} + +% level 4 + +%\def\grammar#1#2{} % a grammar: should never appear in the final output + +\savecslist{parser-prototypes}\yyunion + +% table construction: the macros run to build the contents of the table of productions to be +% typeset. + +\newtoks\table +\newtoks\tokdectoks +\newtoks\opttable +\newtoks\typestable +\newtoks\prectable + +\newtoks\tokstoks +\newtoks\typesset + +\let\rhscont\getsecond +\let\rhscnct\getthird +\let\rhsbool\getfourth + +\newif\ifrhsfull + +\newtoks\yystashlocal +\newtoks\yyformatlocal + +\newif\iftermindex + +\def\doparse#1{% + \table{}\typestable{}\prectable{}\opttable{}% + \parserinit\yyparse#1\yyeof\yyeof\endparseinput\endparse +} + +\long\def\strm[#1]#2.[#3]{#2} +\long\def\inmath#1{$#1$} + +\long\def\stashed#1{\toksa\expandafter{\the\toksa#1}} +\long\def\sflush#1#2{} + +\def\ntt{\noexpand\ntt@} % a convenient shortcut +\def\ntt@{\tt\let\_\UL} + +\def\prodheader#1#2#3#4{% + \yyreadfifo\yyformat\to#3\in\yyformatlocal + \restorecs{table-render}{\strm}\the\yyformatlocal + \let\termindex\writeidxhentry + \prodhead@r{#1}{#2}% + \let\termindex\eatone +} + +\def\headeridxrank{1} % index rank of lhs + +\def\writeidxhentry#1{\write\gindex{% + \nx\nx + \expandafter + \nx + \csname\bisonidxdomain TI\endcsname\headeridxrank#1}% +} + +\def\prodhead@r#1#2{% + \let\idit\prodhdridit + #1\relax\concat\table\toksa\hrhss@p +} + +\def\hrhss@p{\toksa{&\omit\hfil&\omit\hfil&\omit\hfil\cr\noalign{\penalty100}\omit\hfil&\termspostformat}\concat\table\toksa} + +\def\rrhssep#1#2{% + \yyreadfifot\yyformat\to#1\in\yyformatlocal\with\formatsort\relax + \the\yyformatlocal % this will have a chance to change the definition of \rrhss@p + \rrhss@p +} + +\def\rrhss@p{\toksa{\omit\hfil&}\concat\table\toksa} + +\def\arhssep#1#2{% + \yyreadfifo\yyformat\to#1\in\yyformatlocal + \the\yyformatlocal % this will have a chance to change the definition of \arhss@p + \arhss@p +} + +%% between the inline action and next term: + +\def\arhss@p{\toksa{\omit\hfil&\hbox to 2em{\hfil}}\concat\table\toksa} + +\def\rarhssep#1#2{% + \yyreadfifo\yyformat\to#1\in\yyformatlocal + \the\yyformatlocal % this will have a chance to change the definition of \rarhss@p + \rarhss@p +} + +%% between a term and the following action + +\def\rarhss@p{\appendr\table&} + +\newtoks\hstoks + +\def\hspace#1#2{% + \hstoks\yyformat + \yyreadfifot\yyformat\to#1\in\yyformatlocal\with\formatsort\relax + \the\yyformatlocal % may change \hspac@ + \hspac@ +} + +\def\hspac@{% + \appendr\table{ }% +} + +\def\rhs#1#2#3{#1} + +\def\supplybdirective#1#2{% + \edef\next{\nx\s@pplybdirective#1{\the#2}\the#1\nx\bdend}\next +} + +\def\s@pplybdirective#1#2#3\bdend\bdend{% + #1{#3#2\bdend}% +} + +\def\termname#1#2{% + \let\idit\termnameidit + \let\stringify\termnamestringify + \let\optstrextra\optstrextraesc + \let\termindex\writeidxentry + #1\relax\concat\table\toksa + \let\termindex\eatone +} + +\def\bisonidxdomain{B} % marker fo the domain (section of the index) +\def\termidxrank{2} % rank (affects the order in which the entries are + % listed in the index and the listing style) + +\def\writeidxentry#1{\write\gindex{% + \nx\nx + \expandafter + \nx + \csname\bisonidxdomain TI\endcsname\termidxrank#1}% +} + +\let\termindex\eatone + +% index implementation +% note that the rank and domain parameters are handed down by the +% `outer' macro while the `qualifier' (\term...string) is decided +% at the point of invocation + +\def\gidxentry#1#2{% a generic index entry + \iftermindex + \termindex{% + {\nx\nx\nx#1{\charstonumberse#2\end}}% + {\hostparsernamespace}{\nx\the\pageno}{\secno}% + }% + \fi +} + +\def\tidxentry#1#2{% a text index entry + \iftermindex + \write\gindex{% + \nx\nx\expandafter\nx\csname\bisonidxdomain TI\endcsname\termidxrank + {\nx\nx\nx#1{\charstonumberse#2\end}}% + {\indexpseudonamespace}{\nx\the\pageno}{\secno}% + }% + \fi +} + +% + +\newtoks\bdirects + +\def\actbraces#1#2#3#4#5\bdend{% + \yyreadfifo\yyformat\to#3\in\yyformatlocal + \restorecs{table-render}{\strm}% + #5% accumulate all the directives + \edef\next{\the\bdirects}% + \ifx\next\empty + \else + \edef\next{\bdirects{% + $\vtop{\halign{\nx\quad####\nx\hfil&####\nx\hfil\cr\the\bdirects}}$}}\next + \fi + \the\yyformatlocal + \actbrac@s{#1}{#2}{#4}% +} + +\def\actbrac@s#1#2#3{% + \yyreadfifo\yystash\to#3\in\yystashlocal + \unmathstash{#3}% + \edef\next{\toksa{\the\bdirects&\the\yystashlocal\cr}}\next + \bdirects{}% + \concat\table\toksa +} + +\def\unmathstash#1{% + \setbox\z@=\vbox{ + \hsize\maxdimen\emergencystretch\maxdimen + \rightskip\z@ plus 1fill + \let\TeXx\relax\let\stashed\copystashed + \the\yystashlocal\relax + \ifmmode + {}$\aftergroup\unm@thstash % $o that the box can be finished + \else + \aftergroup\eatone + \fi}{#1}% +} + +\def\copystashed#1{#1} + +\def\unm@thstash#1{% + \toksa{\strm[NaN]{\stashed{{}$}}.[NaN]}% $o it cannot be matched if \yystashlocal is read again + \concat\yystashlocal\toksa + \toksa{\strm[#1]{\stashed{${}}}.[#1]}%$ + \appendl\yystash{\the\toksa}% +} + +\def\bpredicate#1#2#3#4#5\bdend{% + \yyreadfifo\yyformat\to#3\in\yyformatlocal + \restorecs{table-render}{\strm}% + #5% accumulate all the directives + \edef\next{\the\bdirects}% + \ifx\next\empty + \bdirects{\quad$\dashv\ \nx\vdash$}% + \else + \edef\next{\bdirects{% + $\vtop{\halign{\nx\quad####\nx\hfil&####\nx\hfil\cr$\dashv\ $&\omit\nx\hfil$\nx\vdash$\cr + \the\bdirects}}$}}\next + \fi + \the\yyformatlocal + \bpredicat@{#1}{#2}{#4}% +} + +\def\bpredicat@#1#2#3{% + \yyreadfifo\yystash\to#3\in\yystashlocal + \unmathstash{#3}% + \edef\next{\toksa{\the\bdirects&\the\yystashlocal\cr}}\next + \bdirects{}% + \concat\table\toksa +} + +\def\bdirective#1#2#3#4{% + \savecslist{local-namespace}\yyunion + \restorecslist{table-render:directives}\yyunion + \toksa{}% + #2% make a directive list + \edef\next{\toksa{$\nx\langle${\ntt #1} &\the\toksa$\nx\rangle$\cr}}\next + \concat\bdirects\toksa + \restorecslist{local-namespace}\yyunion +} + +\def\mergeop#1#2#3{% + \bdirective{merge}{#1}{#2}{#3}% +} + +\def\dprecop#1#2#3{% + \bdirective{dprec}{#1}{#2}{#3}% +} + +\def\sprecop#1#2#3{% + \bdirective{prec}{#1}{#2}{#3}% +} + +\def\rules#1#2#3{#1} + +\def\oneproduction#1#2#3{#1\setrulecontext{}\stopproduction} + +% to make it possible to typeset tokens depending on their context +% the context name is passed to the token typeseting macros; the most +% common context name is the left hand side of a production; special +% context names (such as *left, *right, etc) are defined for terms that are +% not part of a rule; all such context names start with `*' since this +% character cannot be part of a term name + +\def\setrulecontext#1{\def\currentrulecontext{#1}} + +\let\currentrulecontext\empty + +\def\emptyterm{% + \edef\next{\toksa{$\nx\circ$\tidxentry{\termidstring}{emptyrhs}}}\next + \concat\table\toksa +} + +\def\termnameidit#1#2#3#4{% + \yyreadfifot\yyformat\to#3\in\yyformatlocal\with\formatsort\relax + \the\yyformatlocal + \nameproc{#2}% + \peekstash{#4}% + \settermstyle{#1}% + } + +\def\settermstyle#1{% + \edef\next{\toksa{\termmetastyle{% + \gidxentry{\termidstring}{#1}% + \let\nx\idxfont\nx\empty\nx\it\the\toksa\nx\/% + }}}\next +} + +\def\idxinline#1{% index the term in text + \edef\next{\tidxentry{\termidstring}{#1}}\next +} + +\def\termnamestringify#1#2#3#4{% + \nameproc{#2}% + \edef\next{\toksa{{% + \gidxentry{\termstring}{#1}% + \ntt\the\toksa + }}}\next +} + +\def\termmetastyle#1{{#1}} + +\let\peekstash\eatone + +\newif\ifinheader + +\def\prodhdridit#1#2#3#4{% + \setrulecontext{}% + \nameproc{#2}% + \expandafter\setrulecontext\expandafter{\the\toksc}% + \edef\next{\toksa{{% + \gidxentry{\termhdrstring}{#1}% + \nx\inheadertrue\let\nx\idxfont\nx\bf\nx\itbold\the\toksa\nx\/% + }}}\next +} + +\def\charit#1#2#3#4{% + \expandafter\ifx\csname'parser'\hostparsernamespace#1\endcsname\relax + \edef\next{\toksa{{\ntt #1}\gidxentry{\termvstring}{'#1'}}}% + \else + \edef\next{\expandafter\toksa\expandafter{\expandafter\noexpand + \csname'parser'\hostparsernamespace#1\endcsname{\currentrulecontext}\gidxentry{\termvstring}{'#1'}}}% + \fi + \next +} + +\def\anint#1#2#3{% + \toksa{#1}\concat\table\toksa +} + +\def\hexint#1#2#3{% + \toksa\expandafter{\eattwo#1$_{16}$}\concat\table\toksa +} + +\def\optoptsepnone{% + \concat\opttable\postoks +} + +\def\optoptsepsmall{% keep the alignment going but insert a small space + \concat\opttable\postoks + \toksa{\noalign{\smallskip}}\concat\opttable\toksa +} + +\def\prodprodsepsmall{% + \pushothertables + \toksa{\noalign{\penalty-150 \smallskip}}\concat\table\toksa +} + +\def\prodprodsep{% + \pushothertables + \toksa{\noalign{\medskip}}\concat\table\toksa +} + +\def\prodprodseplarge{% + \pushothertables + \toksa{\noalign{\bigskip}}\concat\table\toksa +} + +\def\separatorswitcheq{% + \oneproduction {% + \toksd{\prodprodsepsmall}% + } + \codepropstype\codeassoc {% + \toksd{\optoptsepsmall}% + } +} + +\def\separatorswitchdefaulteq{% + \toksd{\optoptsepnone}% +} + +% a switch for inserting position information into the parsed table +% clobbers \toksd + +\newtoks\postoks + +\def\positionswitch{ + \empty + {% + \postoks{}% semicolons should be invisible + } + \paramdef\oneparametricoption\optionflag\typedecls\vardef + {% + \getfourth{\yy(2)}\to\postoks % the format marker + \getfifth{\yy(2)}\to\toksd % the stash marker + \edef\next{\postoks{\nx\posmark{\the\postoks}{\the\toksd}}}\next + } + \prologuecode\ntermdecls\tokendecls + \flexsstatedecls\flexxstatedecls\flexoptiondecls + {% + \getthird{\yy(2)}\to\postoks % the format marker + \getfourth{\yy(2)}\to\toksd % the stash marker + \edef\next{\postoks{\nx\posmark{\the\postoks}{\the\toksd}}}\next + } + \precdecls + {% + \getfifth{\yy(2)}\to\postoks % the format marker + \getsixth{\yy(2)}\to\toksd % the stash marker + \edef\next{\postoks{\nx\posmark{\the\postoks}{\the\toksd}}}\next + } + \oneproduction + {% + \getsecond{\yy(2)}\to\postoks % the \prodheader + \getfourth{\postoks}\to\toksd % the format marker + \getfifth{\postoks}\to\postoks % the stash marker + \edef\next{\postoks{\nx\posmark{\the\toksd}{\the\postoks}}}\next + } + \codeassoc\codepropstype + {% + \getseventh{\yy(2)}\to\postoks % the format marker + \geteightth{\yy(2)}\to\toksd % the stash marker + \edef\next{\postoks{\nx\posmark{\the\postoks}{\the\toksd}}}\next + } +} + +\def\positionswitchdefault{% + \errmessage{unknown chunk type in: \the\yy(2)}% +} + +\def\posmark#1#2{% +% \yyreadfifo\yyformat\to#1\in\yyformatlocal +% no formattig for locations currently + \restorecs{table-render}{\strm}% +% \the\yyformatlocal + \posm@rk{#2}% +} + +\def\posm@rk#1{% + \yyreadfifo\yystash\to#1\in\yystashlocal + \edef\next{\the\yystashlocal}% + \ifx\next\empty + \postoks{}% + \else + \unmathstash{#1}% + % TODO: move this out + \toksa{}\the\yystashlocal\cleanstash\stripstash + \setbox\z@=\vbox{\setlazyc\the\toksa}% + \ifnum\ht\z@=\z@ + \postoks{}% + \else + \edef\next{\postoks{\noalign{\indent\toksa{}\the\yystashlocal\nx\makestashbox}}}\next + \fi + \fi +} + +\def\codeoptionlist{% + \codepropstype\codeassoc\prologuecode +} + +\def\simpleoptionsplit{% + \oneparametricoption\vardef\paramdef\optionflag +} + +\def\noncodeoptionlist{% + \oneparametricoption\vardef\paramdef\optionflag + \codepropstype\codeassoc\prologuecode +} + +\def\alloptionlist{% + \oneparametricoption\vardef\paramdef\optionflag + \codepropstype\codeassoc\prologuecode + \typedecls\tokendecls\precdecls\oneproduction + \flexsstatedecls\flexxstatedecls\flexoptiondecls +} + +\def\emptyoption{\empty} + +\diagprod\codeoptionlist\noncodeoptionlist\in\codenoncodeseplist +\diagprod\simpleoptionsplit\simpleoptionsplit\in\noncodenoncodeseplist +\diagprod\alloptionlist\emptyoption\in\emptyotherseplist + +% this is a switch for inserting separators between dissimilar items + +\def\separatorswitchneq{% + \classexpand\codenoncodeseplist + {% separate options with code (\codepropstype, \codeassoc) from other options by a small space + \toksd{\optoptsepsmall}% + } + \classexpand\noncodenoncodeseplist + {% + \toksd{\optoptsepnone}% + } + % a separator after the first rule or before or after a semicolon + \classexpand\emptyotherseplist + {% + \toksd{\optoptsepnone}% + } +} + +\setspecialcharsfrom\separatorswitchneq + +\def\separatorswitchdefaultneq{% + \toksd{\prodprodsep}% +} + +\def\pushothertables{% + %token's + \edef\next{\the\tokdectoks}% + \ifx\next\empty + \else + \attachtokentable + \fi + %type's + \edef\next{\the\typestable}% + \ifx\next\empty + \else + \attachtypestable + \fi + %precedence's + \edef\next{\the\prectable}% + \ifx\next\empty + \else + \attachprectable + \fi + % options + \edef\next{\the\opttable}% + \ifx\next\empty + \else + \attachoptionstable + \fi + \concat\table\postoks +} % + +% the various \attach... macros above are defined elsewhere and are the macros that +% determine the actual typesetting of the corresponding tables. + +\let\stopproduction\relax + +\def\tokendecls#1#2#3{% + \savecslist{local-namespace}{\yyunion\termindex}% + \restorecslist{table-render:token-declarations}\yyunion + \let\termindex\writetokenidxentry + \displaytokenrawtrue + \let\currenttokentype\empty#1% + \restorecslist{local-namespace}{\yyunion\termindex}% +} + +\def\typedecls#1#2#3#4{% + \savecslist{local-namespace}{\yyunion\termindex}% + \restorecslist{table-render:type-declarations}\yyunion + \let\termindex\writetokenidxentry + \typesset{}% + #2\relax#1% + \edef\next{\typestable{\the\typestable\nx\onetype{\the\toksa}{\the\typesset}}}\next + \restorecslist{local-namespace}{\yyunion\termindex}% +} + +% \onetype is a typeseting macro defined elsewhere + +\def\flexsstatedecls#1#2#3{% + \savecslist{local-namespace}{\yyunion\termindex}% + \restorecslist{table-render:flex-state-declarations}\yyunion + \let\termindex\writetokenidxentry + \typesset{}% + #1\relax + \edef\next{\typestable{\the\typestable\nx\flexsstatelist{\the\typesset}}}\next + \restorecslist{local-namespace}{\yyunion\termindex}% +} + +\def\flexxstatedecls#1#2#3{% + \savecslist{local-namespace}{\yyunion\termindex}% + \restorecslist{table-render:flex-state-declarations}\yyunion + \let\termindex\writetokenidxentry + \typesset{}% + #1\relax + \edef\next{\typestable{\the\typestable\nx\flexxstatelist{\the\typesset}}}\next + \restorecslist{local-namespace}{\yyunion\termindex}% +} + +% \flexsstatelist and \flexxstatelist are typesetting macros defined elsewhere + +\def\flexoptiondecls#1#2#3{% + \savecslist{local-namespace}{\yyunion\termindex}% + \restorecslist{table-render:flex-option-definitions}\yyunion + \let\termindex\writetokenidxentry + \toksa{}% + #1\relax + \restorecslist{local-namespace}{\yyunion\termindex}% +} + +\def\precdecls#1#2#3#4#5{% #1 type + % #2 tag + % #3 list of symbols + % #4 format pointer + % #5 stash pointer + \savecslist{local-namespace}{\yyunion\termindex}% + \restorecslist{table-render:prec-declarations}\yyunion + \setrulecontext{*#1}% + \let\termindex\writetokenidxentry + \typesset{}#3\toksa{}#2% + \edef\next{\prectable{\the\prectable\noexpand\oneprec{#1}{\the\toksa}{\the\typesset}}}\next + \restorecslist{local-namespace}{\yyunion\termindex}% + \setrulecontext{}% +} + +% \oneprec is a typesetting macro defined elsewhere + +% options typesetting + +\def\oneparametricoption#1#2#3#4{% + \restorecs{table-render:token-declarations}{\braceit\stringify\idit\anint\hexint}% + \toksa{}\toksb{}\toksc{}% + #2% + \edef\next{\noexpand\oneparametricopti@n{#1}{\the\toksa}{\the\toksb}{\the\toksc}}\next +} + +\def\oneparametricopti@n#1#2#3#4{% + \edef\next{#2}% + \ifx\next\empty % there is no identifier + \def\next{#4}% + \ifx\next\empty % there is no digit + \edef\next{\toksa{{\ntt"\the\toksb"}}}\next + \else + \edef\next{\toksa{{\nx\rm\the\toksc}}}\next + \fi + \else + \nameproc{#2}% + \fi % now \toksa contains the value of the parameter + \toksb{#1}% + \let\termindex\writetokenidxentry + \edef\next{\toksa{\gidxentry{\termostring}{#1}$\nx\langle${\nx\bf\the\toksb}$\nx\rangle$&\the\toksa\nx\/\nx\cr}}\next + \let\termindex\eatone + \concat\opttable\toksa +} + +\def\paramdef#1#2#3#4{% + \restorecs{table-render:token-declarations}\braceit + \let\termindex\writetokenidxentry + \edef\next{\toksa{\gidxentry{\termostring}{#2}}}\next + \toksb\expandafter{\the\toksa$\langle${\bf #2}$\rangle$}\toksa{}% + #1% + \let\termindex\eatone + \concat\toksb\toksa + \concat\opttable\toksb +} + +\def\optionflag#1#2#3#4{% + \def\next{#2}% + \ifx\next\empty + \toksb{}% + \else + \toksb{ {\rm(set as $\langle${\bf#2}$\rangle$)}}% + \fi + \let\termindex\writetokenidxentry + \edef\next{\toksa{\gidxentry{\termostring}{#1}$\nx\langle${\nx\bf#1}$\nx\rangle$\nx\rlap{$\nx\,\star$}&\the\toksb\cr}}\next + \let\termindex\eatone + \concat\opttable\toksa +} + +\def\codepropstype#1#2#3#4#5#6#7{% + \yyreadfifo\yyformat\to#4\in\yyformatlocal + \restorecs{table-render}{\strm}% + \the\yyformatlocal % this can change \codepropstyp@ + \codepropstyp@{#2}{#3}{#1}{#5}% +} + +\def\codepropstyp@#1#2#3#4{% + \yyreadfifo\yystash\to#4\in\yystashlocal + \unmathstash{#4}% + \restorecs{table-render:type-declarations}{\idit\stringify\hspace}% + \let\termindex\writetokenidxentry + \typesset{}% + #2% collect all the symbols in \typesset + \edef\next{\toksa{\gidxentry{\termostring}{#3}$\nx\langle${\nx\bf #3}$\nx\rangle$&% + \toksa{}\the\yystashlocal\nx\makestashbox\nx\hfil\cr + \noalign{\nx\smallskip}% + \noalign{\indent$\nx\rlap{\hbox to2em{\nx\hfil$\nx\star$\nx\hfil}}\vcenter{ + \advance\hsize by-\parindent + \emergencystretch10pt\nx\raggedright\noindent\hangafter\z@\hangindent2em\nx\strut\the\typesset\nx\strut}$}% + }}\next + \let\termindex\eatone + \concat\opttable\toksa +} + +\def\codeassoc#1#2#3#4#5#6#7{% + \yyreadfifo\yyformat\to#4\in\yyformatlocal + \restorecs{table-render}{\strm}% + \the\yyformatlocal % this can change \codeass@c + \codeass@c{#1}{#2}{#3}{#5}% +} + +\def\codeass@c#1#2#3#4{% + \yyreadfifo\yystash\to#4\in\yystashlocal + \unmathstash{#4}% + \let\idit\termnameidit + \let\termindex\writetokenidxentry + \toksa{}% in case #1 is empty + #2% put the typeset form of the identifie in \toksa + \toksb\toksa + \edef\next{\toksa{\yystringempty{#1}{}{\gidxentry{\termostring}{#1}}% + $\nx\langle${\nx\bf #1}$\nx\rangle$\nx\quad{\the\toksb}&% + \toksa{}\the\yystashlocal + \nx\makestashbox + \nx\hfil\cr + }}\next + \concat\opttable\toksa + \let\termindex\eatone +} + +\def\vardef#1#2#3#4{% + \yyreadfifo\yyformat\to#3\in\yyformatlocal + \restorecs{table-render}{\strm}% + \the\yyformatlocal % this can change \vard@f + \vard@f{#1}{#2}{#4}% +} + +\def\vard@f#1#2#3{% + \let\idit\termnameidit + \let\stringify\termnamestringify + \let\termindex\writetokenidxentry + #1% put the typeset form of the identifier or string in \toksa + \toksb\toksa + \savecslist{local-namespace}\yyunion + \restorecslist{table-render:variable-definitions}\yyunion + \toksa{}% in case #2 is empty + #2% put the value in toksa + \toksc\toksa + \restorecslist{local-namespace}\yyunion + \let\termindex\eatone + \edef\next{\toksa{$\nx\langle${\nx\bf define}$\nx\rangle$\nx\quad{\the\toksb}&% + \the\toksc\cr + }}\next + \concat\opttable\toksa +} + +\def\prologuecode#1#2#3#4#5{% similar to \actbrac@s + \yyreadfifo\yystash\to#5\in\yystashlocal + \unmathstash{#5}% + \restorecs{table-render}{\strm\stashed}% + \toksa{}\the\yystashlocal + \edef\next{\toksa{\omit\span\omit\nx\cdotfill\cr + \omit\span\omit\toksa{\the\toksa}\nx\makestashbox\nx\cr + \omit\span\omit\nx\cdotfill\cr}}\next + \concat\opttable\toksa +} + +\def\yyunion@tablerender{% + \strm\stashed\rarhss@p\rrhss@p\prodhead@r\hrhss@p\arhss@p\actbrac@s\hspac@\codepropstyp@\vard@f\stopproduction + \termmetastyle\peekstash +} + +\savecslist{table-render}\yyunion +\savecslist{table-render}\yyunion@tablerender + +\def\setprodtable{% + \restorecslist{table-render}\yyunion + \restorecslist{table-render}\yyunion@tablerender +} + +% formatting macros + +\def\midf#1#2{} + +\def\format#1{% + #1% +} +\let\formatlocal\format + +\newtoks\yystashlastcontent % contents of the last action +\newif\ifshowlastaction % if true, show the last action of a flattened set of rules + +\def\flatten{% + \let\stopproduction\stopproduction@flatten + \let\actbrac@s\actbrac@s@flatten + \let\rrhss@p\rrhss@p@flatten + \let\arhss@p\relax + \let\rarhss@p\relax +} + +\def\actbrac@s@flatten#1#2#3{% do everything but add the stash contents to the table + \yyreadfifo\yystash\to#3\in\yystashlocal + \unmathstash{#3}% + \yystashlastcontent\yystashlocal + \futurelet\actsep\actbrac@s@fl@tten +} + +\def\actbrac@s@fl@tten{% + \ifx\actsep\arhssep + \edef\next{% + \toksa{$\nx\ \nx\diamond\nx\ $\tidxentry{\termidstring}{inline_action}}}\next + \concat\table\toksa + \fi +} + +\def\rrhss@p@flatten{% + \toksa{$\ \vert\ $}\concat\table\toksa +}% + +\def\stopproduction@flatten{% + \ifshowlastaction + \toksa\yystashlastcontent + \else + \toksa{\actionfiller}% + \fi + \toksa\expandafter{\expandafter&\expandafter&\the\toksa\cr}\concat\table\toksa +} + +\def\fold{% + \restorecs{table-render}{\actbrac@s\rrhss@p\arhss@p\rarhss@p\stopproduction}% + \ifshowlastaction + \toksa\yystashlastcontent + \else + \toksa{\actionfiller}% + \fi + \toksa\expandafter{\expandafter&\expandafter&\the\toksa\cr}\concat\table\toksa +} + +\def\actionfiller{\omit\quad$\ldots$\hfil} + +\def\inline{% + \let\prodhead@r\prodhead@r@inline + \let\hrhss@p\hrhss@p@inline +} + +\def\prodhead@r@inline#1#2{% + \let\idit\prodhdridit + #1\relax + \setbox\z@=\hbox{\strut\the\toksa\/$\,$\rm:\quad}% + \tempda=\wd\z@\relax + \advance\tempda-2em + \edef\next{\table{\the\table{\the\toksa}}}\next + \hrhss@p +} + +\newif\ifsquashterms + +\def\termspostformat{\ifsquashterms\aftergroup\noexpand\squashtermstrue\fi} + +\def\hrhss@p@inline{% + \edef\next{\toksa{&\termspostformat\hbox to \the\tempda{\hss}}}\next\concat\table\toksa +} + +\def\breakline{% + \let\hspac@\hspac@@breakline +} + +\def\hspac@@breakline{% + \toksa{{$\,\hookleftarrow$}&\omit\hfil&\omit\hfil\cr\omit\hfil&\hbox to 2em{\hfil}}\concat\table\toksa + \restorecs{table-render}\hspac@ +} + +\def\skipheader{% + \let\prodhead@r\prodhead@r@skipheader + \let\hrhss@p\hrhss@p@skipheader +} + +\def\prodhead@r@skipheader#1#2{% + \hrhss@p +} + +\def\hrhss@p@skipheader{\toksa{\omit\hbox to 2em{\hfil}&\termspostformat}\concat\table\toksa\restorecs{table-render}{\hrhss@p}} + +\def\stashtoterm#1{% in case one needs to insert previous stash as a term + % usage: \let\peekstash\stashtoterm + \yyreadfifo\yystash\to#1\in\yystashlocal + \unmathstash{#1}% + \edef\next{\toksb{{% + \nx\restorecs{table-render}{\nx\stashed\nx\strm}% + \toksa{}\the\yystashlocal\nx\makestashbox}}}\next + \def\termmetastyle##1{\the\toksb}% + \restorecs{table-render}\peekstash +} + +\def\resetf{% + \restorecs{table-render}{\prodheader\prodhead@r\hrhss@p\rrhss@p\arhss@p\rhs\termname\actbraces\actbrac@s\rarhss@p\hspac@\rules + \oneproduction\emptyterm\stringify\idit\charit\prodprodsep\onesymbol\strm\stopproduction}% + \squashtermsfalse +} + +\def\prodstyle#1{% to typeset token names in text + {% + \let\optstrextra\optstrextraesc + \nameproc{#1}% + \settermstyle{#1}% + \the\toksa\nobreak + }% +} + +% macros used in typesetting the result of the prologue parsing + +%type declarations + +\restorecslist{parser-strict}\yyunion + + +\def\idit#1#2#3#4{% + \termnameidit{#1}{#2}{#3}{#4}% + \concat\typesset\toksa +} + +\def\stringify#1#2#3#4{% + \termnamestringify{#1}{#2}{#3}{#4}% + \concat\typesset\toksa +} + +\def\hspace#1#2{% + \appendr\typesset{ }% +} + +\def\charit#1#2#3#4{% + \toksa{\.{#2}}% + \concat\typesset\toksa +} + +\def\tagit#1#2#3#4{% + \toksa{\\{#2}}% +} + +\toyyunion{table-render:type-declarations} + +%token declarations + +\newif\iftracetokennames + +\restorecslist{parser-strict}\yyunion + +\def\hspace#1#2{} + +\def\idit#1#2#3#4{\toksa{#2}} + +\def\charit#1#2#3#4{\toksa{'#1'}} + +\def\stringify#1#2#3#4{\toksb{#2}} + +\def\anint#1#2#3{\toksc{#1}} + +\def\hexint#1#2#3{\toksc\expandafter{\eattwo#1$_{16}$}} + +\def\tagit#1#2#3#4{% + \def\currenttokentype{#2}% +} + +\def\braceit#1#2#3{% similar to \actbrac@s + \yyreadfifo\yystash\to#3\in\yystashlocal + \unmathstash{#3}% + \restorecs{table-render}{\strm\stashed}% + \toksa{}\the\yystashlocal + \edef\next{\toksa{&\toksa{\the\toksa}\nx\makestashbox\nx\cr}}\next +} + +\def\onesymbol#1#2#3{% #1 is the macro name used internally by bison (\idit{}{}{}{}) + % #2 is the integer value (\anint{}{}{}) + % #3 is the string value (\stringify{}{}{}{}) + \toksa{}\toksb{}\toksc{}% + #1#2#3\relax + \edef\next{\noexpand\onesymb@l{\the\toksa}{\the\toksc}{\the\toksb}}\next +} + +\def\onesymb@l#1#2#3{% #1 is the macro name used internally by bison + % #2 is the integer value + % #3 is the string value + \let\optstrextra\optstrextraesc + \yystringempty{#3}{}{\nameproc{#3}\tokstoks\toksa}% + \yystringempty{#1}{}{\nameproc{#1}}% + \iftracetokennames\derrmessage{token: \the\toksa, string: \the\tokstoks}\fi + \toksb\expandafter{\currenttokentype}% + \edef\next{% + \tokdectoks{\the\tokdectoks + \noexpand\toksdefline + {\the\toksa}% + {% + \yystringempty{#1}{}{\gidxentry{\termidstring}{#1}}% + \yystringempty{#3}{}{\gidxentry{\termstring}{#3}}% + }% + {\yytoksempty\toksb{auto}{\the\toksb}}% + {#2}% + {\the\tokstoks}% + }% + }\next + \restorecs{nameparser}{\optstrextra}% +} + +\def\defidxrank{0} % index rank of definitions + +\def\writetokenidxentry#1{\write\gindex{% + \nx\nx + \expandafter + \nx + \csname\bisonidxdomain TI\endcsname\defidxrank#1}% +} + +\toyyunion{table-render:token-declarations} + +%precedence declarations + +\restorecslist{parser-strict}\yyunion + +\def\idit#1#2#3#4{% + \termnameidit{#1}{#2}{#3}{#4}% + \concat\typesset\toksa +} + +\def\stringify#1#2#3#4{% + \termnamestringify{#1}{#2}{#3}{#4}% + \concat\typesset\toksa +} + +\def\charit#1#2#3#4{% + \expandafter\ifx\csname'parser'\hostparsernamespace#1\endcsname\relax + \edef\next{\toksa{{\ntt #1}\gidxentry{\termvstring}{'#1'}}}% + \else + \edef\next{\expandafter\toksa\expandafter{\expandafter\noexpand + \csname'parser'\hostparsernamespace#1\endcsname{\currentrulecontext}\gidxentry{\termvstring}{'#1'}}}% + \fi + \next + \concat\typesset\toksa +} + +\def\anint#1#2#3{% + \edef\next{\toksa{${}=\hbox{\ntt#1}$}}\next + \concat\typesset\toksa +} + +\def\hexint#1#2#3{% + \toksa\expandafter{\eattwo#1}% + \edef\next{\toksa{${}=\hbox{\ntt\the\toksa}_{16}$}}\next + \concat\typesset\toksa +} + +\def\hspace#1#2{% + \appendr\typesset{ }% +} + +\def\tagit#1#2#3#4{% + \toksa{\\{#2}}% +} + +\def\symbolprec#1#2{% + #1#2% +} + +\toyyunion{table-render:prec-declarations} + +% variable definitions + +\restorecslist{parser-strict}\yyunion + +\def\idit#1#2#3#4{\toksa{#2}} + +\def\stringify#1#2#3#4{\toksa{#2}} + +\def\bracedvalue#1#2#3{% similar to \actbrac@s + \yyreadfifo\yystash\to#3\in\yystashlocal + \unmathstash{#3}% + \restorecs{table-render}{\strm\stashed}% + \toksa{}\the\yystashlocal + \edef\next{\toksa{\toksa{\the\toksa}\nx\makestashbox}}\next +} + +\toyyunion{table-render:variable-definitions} + +% directives + +\restorecslist{parser-strict}\yyunion + +\def\idit#1#2#3#4{% + \termnameidit{#1}{#2}{#3}{#4}% +} + +\def\stringify#1#2#3#4{% + \termnamestringify{#1}{#2}{#3}{#4}% +} + +\def\tagit#1#2#3#4{% + \toksa{\\{#2}}% +} + +\def\anint#1#2#3{% + \toksa{#1}% +} + +\def\hexint#1#2#3{% + \toksa\expandafter{\eattwo#1$_{16}$}% +} + +\toyyunion{table-render:directives} + +% flex state declarations + +\restorecslist{parser-strict}\yyunion + +\def\idit#1#2#3#4{% + \nameproc{#2}% + \edef\next{\toksa{{% + \gidxentry{\termttstring}{#1}% + \ntt\the\toksa + }}}\next + \concat\typesset\toksa +} + +\def\hspace#1#2{% + \appendr\typesset{ }% +} + +\toyyunion{table-render:flex-state-declarations} + +% flex option definitions + +\restorecslist{parser-strict}\yyunion + +\def\flexoptionpair#1#2{% + #1% + \edef\next{#2}% + \ifx\next\empty % there is no rihgt hand side + \edef\next{\toksa{$\nx\langle${\ntt\the\toksa}$\nx\rangle_{\rm f}\,\star$&\cr}}\next + \else + \toksb\toksa\toksa{}#2% + \edef\next{\toksa{$\nx\langle${\ntt\the\toksb}$\nx\rangle_{\rm f}$&\nx\it\the\toksa\nx\/\nx\cr}}\next + \fi + \concat\opttable\toksa +} + +\def\idit#1#2#3#4{\toksa{#2}} + +\def\stringify#1#2#3#4{\toksa{{\ntt@"#2"}}} + +\def\hspace#1#2{} + +\toyyunion{table-render:flex-option-definitions} + +% rule listing macros + +\restorecslist{parser-prototypes}\yyunion % we just want to ignore the non-rule related code + +\def\prodheader#1#2#3#4{% + #1\relax + \lastlastname\lastname + \setnumname\numname + \lastname{}% + #2\relax + \edef\next{\toksc{\numname:}\toksd{\noexpand\lhs{\the\lastlastname}{\the\lastname}}}\next +} + +\def\rrhssep#1#2{} +\def\arhssep#1#2{} +\def\rarhssep#1#2{} +\def\hspace#1#2{} + +\def\rhs#1#2#3{% + \concat\toksa\toksc + \concat\toksb\toksd + #1\relax + \edef\next{\toksb{\noexpand\onerule{\the\toksb}}}\next + \appendr\toksa\def + \possibleimplicitfalse + \yyreplacestring\toksa\in\newsymswitch\with\toksb + \toksa{}\toksb{}% +} + +\newtoks\lastname +\newtoks\lastlastname + +\def\termname#1#2{% + \flushact + #1\relax + \lastlastname\lastname + \setnumname\numname + \lastname{}% + #2\relax + \appendr\toksa{ \numname}\appendr\toksb{\noexpand\term{\the\lastlastname}{\the\lastname}}% +} + +\def\setnumname#1{% + \expandafter\let\expandafter\next\csname term\parsernamespace\the\lastname \endcsname + \ifx\next\relax % this is a terminal that was renamed + \expandafter\ifx\csname token\parsernamespace\the\lastname \endcsname\relax % this is probably a symbol from another grammar + \def#1{-1}% + \errmessage{token \csname token\parsernamespace\the\lastname \endcsname\space is undefined}% + \else + \expandafter\tempca\csname token\parsernamespace\the\lastname \endcsname + \edef#1{\fgetelemof{yytranslate}\at\tempca}% + \fi + \else + \let#1\next + \fi +} + +\def\actbraces#1#2#3#4#5\bdend{% + \flushact + \lastname{}% + #2\relax + \edef\next{\lastactsym{\the\lastname}}\next + \possibleimplicittrue +} + +\def\rules#1#2#3{#1} + +\def\oneproduction#1#2#3{#1} + +\def\emptyterm{% + \flushact + \lastname{}% +} + +\def\stringify#1#2#3#4{% + \lastname{"#1"}% +} + +\def\idit#1#2#3#4{% + \lastname{#1}% +} + +\def\charit#1#2#3#4{% + \lastname{'#1'}% +} + +\def\prodprodsep{} + +\def\onesymbol#1#2#3{} + +\def\anint#1#2#3{% + \lastname{#1}% +} + +\def\hexint#1#2#3{% + \lastname\expandafter{\expandafter\number\eattwo#1$_{16}$}% +} + +\newtoks\lastactsym +\newif\ifpossibleimplicit + +\def\flushact{% + \ifpossibleimplicit + \appendr\toksa{ @implicit@}\appendr\toksb{\noexpand\implicitterm{@implicit@}{\the\lastactsym}}% + \lastactsym{}% + \possibleimplicitfalse + \fi +} + +\savecslist{symbols}\yyunion + +% name parser macros + +\def\idstr#1#2{% + \toksb{#1}% + \concat\toksa\toksb + \toksb{#2}% + \concat\toksc\toksb +} + +\def\chstr#1#2{% + \toksb{{\ntt@#1}}% + \concat\toksa\toksb + \toksb{#2}% + \concat\toksc\toksb +} + +\def\sfxi#1#2{\toksb{\/${}_{\idxfont#1}$}\concat\toksa\toksb} + +\def\sfxn#1#2{\toksb{#1}\concat\toksa\toksb} + +\def\dotsp{\futurelet\next\d@tsp} + +\def\d@tsp{% + \ifx\next\sfxi + \else + \ifx\next\qual + \else + \toksb{.}\concat\toksa\toksb + \fi + \fi +} + +\def\optstr#1#2{% + \toksb\expandafter{\eatone#1}% + \optstrextra + \concat\toksa\toksb + \toksb{#2}% + \concat\toksc\toksb +} + +\def\optstrextra{% + \edef\next{\toksb{{$\nx\ulcorner$\ntt\the\toksb$\nx\urcorner$}}}\next +} + +\def\optstrextraesc{% + \edef\next{\toksb{{$\nx\langle$\ntt\the\toksb$\nx\rangle$}}}\next +} + +\def\qual#1#2{\toksb{\/${}_{\rm#2}$}\concat\toksd\toksb} + +\let\idxfont\relax + +\savecs{nameparser}{\idstr\chstr\sfxi\sfxn\qual\optstr\dotsp\optstringextra\idxfont} + +\newtoks\namechars + +\newif\iftracebadnames +\newif\iftracenames + +\def\nameproc#1{% + \ifbootstrapmode + \toksa{}% + \else + \savecs{local-namespace}\getcurrentparser + \tosmallparser + \basicparserinit + \yyparse#1\yyeof\yyeof\endparseinput\endparse + \ifyyparsefail + \iftracebadnames + \ferrmessage{bad name: #1}% + \fi + \toksa{#1}\toksc{}% + \else + \toksa{}\toksb{}\toksc{}\toksd{}% + \iftracenames + \ferrmessage{parsed name: \the\namechars}% + \fi + \the\namechars\relax + \iftracenames + \ferrmessage{processed name: \the\toksa<identifier>, \the\toksb<suffices>, \the\toksc<hash name>, \the\toksd<options>}% + \fi + \expandafter\ifx\csname'parser'\hostparsernamespace\the\toksc \endcsname\relax + \else + \toksa\expandafter{\csname'parser'\hostparsernamespace\the\toksc \endcsname}% + \appendr\toksa{{\currentrulecontext}}% + \fi + \concat\toksa\toksd + \fi + \restorecs{local-namespace}\getcurrentparser + \getcurrentparser + \fi +} + +%% token typesetting macros + +\def\setsafe#1{\def\saferword{#1}\setspecialcharsfrom\saferword} +\def\prettyword#1{\setsafe{#1}\expandafter\edef\csname'parser'\parsernamespace\saferword\endcsname##1{{\ntt\lowercase{\saferword}}}} +\def\prettytoken#1{\setsafe{#1}\expandafter\edef\csname'parser'\parsernamespace\saferword\endcsname##1{{\ntt\saferword}}} +\def\prettytoken@#1{\toksa{}\numberstocharsandspaces#1\end\expandafter\edef + \csname'parser'\parsernamespace\the\toksa\endcsname##1{{\ntt\the\toksa}}% +} +\def\prettywordpair#1#2{\setsafe{#1}\expandafter\def\csname'parser'\parsernamespace\saferword\endcsname##1{{\ntt@#2}}} +\def\prettywordpair@#1#2{% + \setsafe{#1}\toksa{}\numberstocharsandspaces#2\end\expandafter\nameproc\expandafter{\the\toksa}% + \expandafter\edef\csname'parser'\parsernamespace\saferword\endcsname##1{% + \noexpand\ifdisplaytokenraw + {\ntt\saferword}% + \noexpand\else + {\ntt\def\noexpand\_{\char`\noexpand\_}\the\toksa}% + \noexpand\fi + }% +} +\def\prettywordpair@@#1#2{\setsafe{#1}\expandafter\def\csname'parser'\parsernamespace\saferword\endcsname##1{{#2}}} + +% the bootstrap macros + +\def\initbootstrap{% + \restorecslist{bootstrap}\yyunion +} + +\restorecslist{parser-prototypes}\yyunion + +\def\tokendecls#1#2#3{#1} + +\def\stringify#1#2#3#4{\toksa{"#1"}} + +\def\idit#1#2#3#4{\toksb{#1}} + +%\def\anint#1#2#3{\toksc{#1}}% this definition is not needed as all + %information is extracted from yytname + +% note that the definitions below do not handle cases such as +%token '{' "left brace" since the lexer knows how to return '{' + +\def\onesymbol#1#2#3{% + \toksa{}\toksb{}%\toksc{}% + #1#2#3% + \yytoksempty\toksa{\expandafter\charstonumbers\the\toksb\end}% + {\expandafter\toksa\expandafter{\expandafter}\expandafter\charstonumbers\the\toksa\end}% + \yytoksempty\toksb{% + \yytoksempty\toksa{}{% + \immediate\write\tokendefs{\noexpand\tokeneq{\the\toksb}{\the\toksa}}% + }% + }{% + \immediate\write\tokendefs{\noexpand\tokeneq{\the\toksb}{\the\toksa}}% + }% +} + +\def\flexsstatedecls#1#2#3{% bootstrap parser does not produce state declarations so it is fine to share states + \savecslist{local-namespace}\yyunion + \restorecslist{bootstrap:flex-state-declarations}\yyunion + #1\relax + \restorecslist{local-namespace}\yyunion +} + +\let\flexxstatedecls\flexsstatedecls + +\savecslist{bootstrap}\yyunion + +\restorecslist{parser-strict}\yyunion + +\def\idit#1#2#3#4{{\immediate\write\stlist{_register_name(#1);}}} + +\def\hspace#1#2{} + +\savecslist{bootstrap:flex-state-declarations}\yyunion + +\def\charstonumberse#1\end{% + \yystringempty{#1}{}% + {\yystartsinspace{#1}{{\number`\ }\charstonumber@@#1\end}{\charstonumbers@#1\end}}% +} + +\def\charstonumbers@#1{% + {\number`#1}\charstonumberse +} + +\def\charstonumber@@#1 {\charstonumberse} + +\def\charstonumbers#1\end{\edef\next{\toksa{\charstonumberse#1\end}}\next} diff --git a/support/splint/tex/yyxunion.sty b/support/splint/tex/yyxunion.sty new file mode 100644 index 0000000000..fb0d2460b3 --- /dev/null +++ b/support/splint/tex/yyxunion.sty @@ -0,0 +1,33 @@ +% Copyright 2012-2015, 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/>. + +% the original, minimal bootstrapping macros were designed to process +% \prodstyle{\%token} declarations only and are enough to establish the +% interface between the \bison\ parser and the \bison\ lexer; to serve +% the secondary task of providing typesetting information to +% the \bison\ parser, all forms of token declarations must be processed. + +\restorecslist{bootstrap}\yyunion % get the original bootstrap macros + +\def\precdecls#1#2#3#4#5{#3} + +\def\symbolprec#1#2{% + \toksa{}\toksb{}% + #1% + \yytoksempty\toksb{}{\immediate\write\tokendefs{\noexpand\tokenpp{\the\toksb}}}% +} + +\savecslist{bootstrap}\yyunion |