% Copyright 2012-2022, 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 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{\bits{}\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}

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

% colors

\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

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

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

% 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

%\registerlegend{{8}{\noexpand\phantom{B}}}