\begin{filecontents*}[overwrite]{dat.hex}
00            00 00 00 00 00 00 00 00
08            00 00 00 00 00 00 00 00
10            00 00 00 00 00 00 00 00
7fffffffee10  58 ee ff ff ff 7f 00 00
7fffffffee18  55 24 40 00 00 00 00 00
7fffffffeea0  55 24 40 00 00 00 00 00
7fffffffeea8  55 24 40 00 00 00 00 00
\end{filecontents*}
\begin{filecontents*}[overwrite]{dat-small.hex}
0            00 00
2            00 00
4            00 00
6            00 00
8            00 00
\end{filecontents*}

\documentclass{ltxdoc}

\usepackage{hexdumptikz}

\usepackage[numbered]{hypdoc}
\usepackage{csquotes}
\usepackage[T1]{fontenc}
\usepackage{amsmath}
\usepackage{cleveref}
\usepackage[per-mode=fraction,sticky-per]{siunitx}
\newcommand{\TikZ}{Ti\emph{k}Z}

\usepackage{naive-ebnf}

\usepackage{tcolorbox}
\tcbuselibrary{listingsutf8,documentation,breakable,skins}
\tcbset{
	docexample/.append style={
		skin=enhanced,
		fonttitle=\bfseries\sffamily,
	}
}
\colorlet{ExampleFrame}{blue!60}
\makeindex
\tcbset{
	doc head={colback=yellow!10!white,interior style=fill},
	doc head key={colback=magenta!5!white,interior style=fill},
	index colorize,
	index annotate,
	index format=pgfsection,
}

\GetFileInfo{hexdumptikz.sty}
\title{\textsf{hexdumptikz} -- \fileinfo}
\author{Lukas Heindl\thanks{%
		E-Mail: \href{oss.heindl+latex@protonmail.com}{oss.heindl+latex@protonmail.com}\\%
		Issue tracker: \href{https://codeberg.org/atticus-sullivan/hexdumptikz/issues}{codeberg.org/atticus-sullivan/hexdumptikz/issues}\\%
		Codeberg (mirror): \href{https://codeberg.org/atticus-sullivan/hexdumptikz}{codeberg.org/atticus-sullivan/hexdumptikz}\\%
}}
\date{\fileversion~from \filedate}

\addtolength{\textwidth}{\oddsidemargin}

\setlength\marginparwidth{0pt}
\setlength\oddsidemargin{0pt}
\setlength\evensidemargin{0pt}

\begin{document}

\maketitle

\begin{abstract}
Showing hexdumps\footnote{\url{https://en.wikipedia.org/wiki/Hex_dump}} is a common task in some fields.
The most rudimentary form doing this in \LaTeX is using a simple listings package (like \refPkg{listings}).
But often just showing the data is not enough.
Instead, it needs to be annotated and explained.

This package leverages \refPkg{tikz} for printing the hexdumps.
This way, it is very easy to highlight and annotate parts of the hexdump afterwards.
But be careful, for large dumps, the \TikZ{} drawing alone can take some time.

One key aspect of this package is that it tries to avoid calculating on the addresses as much as possible.
In the cases where it is unavoidable, the package calculates just with the last digits of the addresses.
This way the package tries to avoid issues where the address/offset gets too large\footnote{This happens quickly if hexdump is the dump of a processes the stack on a 64-bit machine} to represent it as an integer in \LaTeX{}.

Keep in mind the drawing happens with \TikZ{} and every byte gets its own node.
Thus, it may take a while to show larger hexdumps\footnote{According to my measurements it really it \TikZ{} which is responsible for the slowdown and not the selection/styling logic or the parser}.
\end{abstract}

\section{General remarks on the documentation}
Note this documentation makes use of \emph{EBNF}\footnote{\url{https://en.wikipedia.org/wiki/Extended_Backus\%E2\%80\%93Naur_form}} for specifying valid input of some parsers.
For typesetting these, the documentation uses \refPkg{naive-ebnf} which is not \qty{100}{\percent} in line with \emph{ISO/IEC 14977}.
So if in doubt, better check that package's documentation ($1^\text{st}$ page) for the notation.

\section{Usage} \label{usage}

\begin{docEnvironment}[]{hexdumptikz}{\oarg{options}\marg{filename/path}}
	The environment which scopes working with a single hexdump.
	The commands \refCom{hexdumptikzPrint} and \refCom{hexdumptikzLabelBytes} are intended to be only used within this environment.

	Specify the path to the / the filename of the file with the hexdump in it as \marg{filename/path}.
	\oarg{options} allows to set keys from the \texttt{/hexdumptikz} space (see \cref{options}, searches also \texttt{/tikz}) for the whole scope/group.

	This still is inside a \TikZ{} environment (it just opens a new \TikZ{}-\texttt{scope}), so you may use arbitrary additional \TikZ{} commands inside the environment.
\end{docEnvironment}

\begin{docCommand}[]{hexdumptikzPrint}{\oarg{options}\marg{selector}}
	Read/Parse the hexdump as far as needed to fulfill the \marg{selector} and generate the \TikZ{} nodes to show the dump.
	See \cref{selector} for how to specify the selector.

	Note for this purpose, the selectors must \emph{not overlap} and be sorted in the order of occurence (thus usually it does not make sense to mix address and index selectors).
	Also here it does not make sense to specify a \emph{style} (but it is not an error).

	\oarg{options} allows to set keys from the \texttt{/hexdumptikz} space (see \cref{options}, searches also \texttt{/tikz}).
	Common options here are \refKey{/hexdumptikz/tikz}, \texttt{/hexdumptikz/show*}, \refKey{/hexdumptikz/styled bytes} and redefining styles automatically used when drawing.
	You can also set options regarding the parsing here, but usually it makes more sense to specify these for the whole environment.
\end{docCommand}

\begin{docCommand}[]{hexdumptikzLabelBytes}{\oarg{options}\marg{start-addr}\marg{end-addr}}
	Label/Highlight a sequence of bytes in the hexdump.
	It will draw a path around the selected bytes (a rectangle by default).

	The sequence of bytes is specified by \marg{start-addr} and \marg{end-addr}.
	It works across multiple lines and can jump over gaps and skipped offsets.
	Note you can only specify based on addresses, not based on indices.

	\oarg{options} is evaluated in the \texttt{/hexdumptikz} space (see \cref{options}, searches also \texttt{/tikz}) and allows customizing how the path is drawn.

	Note this command relys on information gathered during \refCom{hexdumptikzPrint} and thus needs to be executed after that command.
	Also \refEnv{hexdumptikz} cleans up its state in the end, so \refCom{hexdumptikzLabelBytes} must be executed within that environment.
\end{docCommand}

\begin{docCommand}[]{hexdumptikzLabelBytesFallback}{\oarg{options}\marg{start}\marg{end}}
	Basically the same as \refCom{hexdumptikzLabelBytes} but does not rely on information gathered during \refCom{hexdumptikzPrint}.
	Thus, it can also be used outside of \refEnv{hexdumptikz} but the line does not perfectly fit the right row in the hexdump.
	\Cref{simple-example} shows an example for the difference.
\end{docCommand}

\subsection{Simple Example} \label{simple-example}
\tcbinputlisting{/tcb/docexample,/tcb/documentation listing style,listing only,listing file=dat.hex,title={file: \texttt{dat.hex}}}
\begin{dispExample*}{listing options={language=[LaTeX]TeX},breakable,title={A simple example}}
\begin{tikzpicture}
  \begin{hexdumptikz}{dat.hex}
    \hexdumptikzPrint{0,0x08,0x7fffffffee18-0x7fffffffeea8}
    \hexdumptikzLabelBytes[rounded corners]{0x2}{0xa}
  \end{hexdumptikz}
  \hexdumptikzLabelBytesFallback[rounded corners,tikz=red]{0x2}{0xa}
\end{tikzpicture}
\end{dispExample*}

\subsection{Hexdump-Parser} \label{hd-parser}
This package can implement multiple hexdump-parsers.
But currently only one is implemented.

% \begin{docKey}[hexdumptikz]{parser}{=\meta{parser}}{}
% \end{docKey}

\subsubsection{hd} \label{hd-parser-hd}
This parser works with most formats.
At some places it can be adjusted slightly to work with slightly different formats.

Note this parser stops parsing a line after \refKey{/hexdumptikz/bytes per row} have been parsed from the line (continues with the next line then).

This is the whole grammar which it can parse (for some of the optional stuff, specific keys need to be set):

\begin{ebnf}
	<hexdump> := { <hexdumpline> [ '\textbackslash n' ] }+
	\\
	<hexdumpline> := <address> [ "0x" ] <values>
	\\
	<address> := { 'SPACE' } [ "0x" ] { <hexdigit> }+ { 'SPACE' } [ ":" ] { 'SPACE' }
	\\
	<hexdigit> := /[0-9a-fA-F]/
	\\
	<values> := { { 'SPACE' } <hexdigit> <hexdigit> { 'SPACE' } }
\end{ebnf}

% \begin{docKey}[hexdumptikz]{parser}{=\meta{parser}}{}
% \end{docKey}

\subsection{Selector} \label{selector}
\begin{ebnf}
	<selector> := { <selectorEle> "," } <selectorEle>
	\\
	<selectorEle> := <spec> [ "$\vert$" <predicate> ] [ "->" <style> ]
	\\
	<spec> := ( <range> | <atom> | <gap> )
	\\
	<gap> := "x"
	\\
	<range> := ( <addr> "-" <addr> | <idx+x> "-" <idx+x> )
	\\
	<atom> := ( <addr> | <idx+x> )
	\\
	\\
	<idx+x> := <idx> [ "/" /[0-9]+/ ]
	\\
	<idx> := /[0-9]+/
	\\
	<addr> := "0x" /[0-9a-fA-F]+/
	\\
	<style> := /'tikz-code or style'/
	\\
	<predicate> := [ ( "x" | "y" ) "/" ] ( "odd" | "even" | <pred\_mod> )
	\\
	<pred\_mod> := "mod (" { 'SPACE' } /[0-9]+/ { 'SPACE' } "," { 'SPACE' } /[0-9]+/ { 'SPACE' } ")"
\end{ebnf}

\subsubsection{Predicates}
Predicates allow to select a specific subset of rows/bytes within the given range.
They usually operate on one of the axes \texttt{x} or \texttt{y}. If no axis is given, \texttt{x} is assumed as default.

\paragraph{Modulo}
The most common predicate is the modulo predicate.
The predicate \texttt{mod(m,r)} checks the element $e$ ($x$ or $y$ index) as follows: $e \bmod m \overset{!}{=} r$.

The following shortcuts are defined:
\begin{itemize}
	\item[\texttt{odd}]  $\to$ \texttt{mod(2,1)}
	\item[\texttt{even}] $\to$ \texttt{mod(2,0)}
\end{itemize}

Note that the selector is usually split arounc \texttt{,}.
Thus, when using \texttt{mod} directly, you need to enclose it with braces, for example like this \texttt{\{mod(2,1)\}}.

\subsection{Generated Nodes} \label{nodes}
Notation:
\begin{itemize}
	\item[\texttt{in\_idx}] index of the row based on the \emph{input} aka linenumber in the input file
	\item[\texttt{out\_idx}] index of the row based on the \emph{output} aka line-/rownumber in the shown hexdump
	\item[\texttt{horizontal\_idx}] \emph{x-index}
	\item[\texttt{end}] refers to the last node in one direction
	\item[\texttt{end-end}] special: the last byte-node in the last row.
\end{itemize}

Generated node-names: (Note: \texttt{*\_idx} start at 0)
\begin{itemize}
	\item Regular Address-Nodes:
		\begin{itemize}
			\item \texttt{hexdumptikz-in-<in\_idx>}
			\item \texttt{hexdumptikz-out-<out\_idx>}
			\item \texttt{hexdumptikz-<padded\_offset>}
		\end{itemize}
	\item End Address-Nodes:
		\begin{itemize}
			\item \texttt{hexdumptikz-end}
		\end{itemize}
	\item Regular Byte-Nodes:
		\begin{itemize}
			\item \texttt{hexdumptikz-in-<in\_idx>-<horizontal\_idx>}
			\item \texttt{hexdumptikz-out-<out\_idx>-<horizontal\_idx>}
			\item \texttt{hexdumptikz-<padded\_offset>-<horizontal\_idx>}
		\end{itemize}
	\item End Byte-Nodes:
		\begin{itemize}
			\item \texttt{hexdumptikz-in-<in\_idx>-end}
			\item \texttt{hexdumptikz-out-<out\_idx>-end}
			\item \texttt{hexdumptikz-<padded\_offset>-end}
			\item \texttt{hexdumptikz-end-end}
		\end{itemize}
	\item Gap-Nodes: (Note: \texttt{gap\_num} starts at 1)
		\begin{itemize}
			\item \texttt{hexdumptikz-in-<in\_idx>-gap<gap\_num>}
			\item \texttt{hexdumptikz-out-<out\_idx>-gap<gap\_num>}
			\item \texttt{hexdumptikz-<padded\_offset>-gap<gap\_num>}
		\end{itemize}
\end{itemize}

\subsubsection{Nodename-helpers} \label{nodename-helpers}
\begin{docCommand}[]{hexdumptikzAddrToNodename}{\marg{address}}
	After \refCom{hexdumptikzPrint} and within \refEnv{hexdumptikz}, this allows transforming the address of a byte to its node-name.
	This allows (moreover simplifies) drawing custom annotations into the hexdump.

	Note this is the same functionality \refCom{hexdumptikzLabelBytes} uses internally.
\end{docCommand}

\begin{docCommand}[]{hexdumptikzAddrToRow}{\marg{address}}
	After \refCom{hexdumptikzPrint} and within \refEnv{hexdumptikz}, this allows transforming the address of a byte to its row-index.
	This allows (moreover simplifies) drawing custom annotations into the hexdump.

	Note this is the same functionality \refCom{hexdumptikzLabelBytes} uses internally.
\end{docCommand}

\begin{docCommand}[]{hexdumptikzAddrToCol}{\marg{address}}
	After \refCom{hexdumptikzPrint} and within \refEnv{hexdumptikz}, this allows transforming the address of a byte to its column-index.
	This allows (moreover simplifies) drawing custom annotations into the hexdump.

	Note this is the same functionality \refCom{hexdumptikzLabelBytes} uses internally.
\end{docCommand}

\section{Options} \label{options}
All keys reside inside the \texttt{/hexdumptikz} space.
Note this space also searches the \texttt{/tikz} space.
This way, you can intuitively set e.g. \texttt{rounded corners}.
But on the other hand, unknown keys are always reported as unknown in \texttt{/tikz} and not in \texttt{/hexdumptikz}.
Also, some keys do not work globally with a plain \cs{tikzset}.
For such cases you may use \refKey{/hexdumptikz/tikz}.

\begin{docKey}[hexdumptikz]{tikz}{=\meta{tikz-keys}}{}
	Allows to set tikz-keys which do not work \enquote{globally} with \cs{tikzset}.
	An example is setting the color to \texttt{red}.

	Internally, every drawing generated by this package is enclosed by a \TikZ{}-\texttt{scope}.
	Thus, this key simply appends to the \texttt{/tikz/every scope} style.
\end{docKey}

\begin{docKey}[hexdumptikz]{name prefix}{=\meta{prefix}}{}
	Works similar like \texttt{/tikz/name prefix}.

	This will also set \texttt{name prefix} on the following tikz-scope.
	Thus, when you draw manually in e.g. \refEnv{hexdumptikz} this key is effective.

	See \cref{nodename-example} for why this is useful.
\end{docKey}

The following subsections describe options/keys and styles grouped by where they apply to.
You may of course set them at other places too, therby changing the scope of the setting (e.g. set \refKey{/hexdumptikz/show addr} at the \refEnv{hexdumptikz} for all \refCom{hexdumptikzPrint} within the environment).

\subsection{Print Hexdump}

\begin{docKey}[hexdumptikz]{addr len}{=\meta{len}}{initial: 12} % currently exclusively used for padding
	Specify the length of the addresses (the number of hex-digits without the leading \texttt{0x}).
	This is the length to which addresses will get padded to.

	Note if the real addresses have more digits, there might be issues with the selection and/or styling mechanism.

	Further note, this affects the padding used for \refKey{/hexdumptikz/show addr padded} as well as the padding used internally for the selection and styling mechanism.
\end{docKey}

\begin{docKey}[hexdumptikz]{bytes per row}{=\meta{BPR}}{initial: 8}
	Specify the amount of bytes normally present on one row.

	This primarily is used for calculating the length of the addresses suffix which is used when calculating on addresses.
	But parsers also may stop parsing a line after parsing this amount of bytes (each with two hex-digits).
\end{docKey}

\subsubsection{Drawing}
\begin{docKey}[hexdumptikz]{bytes sep after}{=\meta{number}}{initial: 64}
	Allows to insert a horizontal separating space in the hexdump.
	This key specifies after how many bytes (\meta{number}) the separator should be inserted.

	Note: The size of the separator is determined by \refKey{/hexdumptikz/bytes sep}
\end{docKey}

\begin{docKey}[hexdumptikz]{bytes sep}{=\meta{dimension}}{initial: 2em}
	Allows to insert a horizontal separating space in the hexdump.
	This key specifies the size of the separator (\meta{dimension}).

	Related: \refKey{/hexdumptikz/bytes sep after}
\end{docKey}

\begin{docKey}[hexdumptikz]{show addr}{=\meta{bool}}{initial: true, default: true}
	Whether the hexdump should display the nodes with the addresses/offsets.

	Note for generality, the address nodes always are present.
	But when set to \texttt{false}, they are placed so that they are not visible and do not occupy additional space.
\end{docKey}

\begin{docKey}[hexdumptikz]{show addr base}{=\meta{bool}}{initial: true, default: true}
	Whether the addresses shown in the hexdump should be prefixed with \texttt{0x} to indicate the hexadecimal base.

	Note this is purely aesthetic and is irrelevant for how to specify addresses when selecting bytes/rows.
\end{docKey}

\begin{docKey}[hexdumptikz]{show addr padded}{=\meta{bool}}{initial: false, default: true}
	Whether the addresses shown in the hexdump should be padded to \refKey{/hexdumptikz/addr len}.

	Note this is purely aesthetic, internally addresses are always padded to \refKey{/hexdumptikz/addr len}.
\end{docKey}

\begin{docKey}[hexdumptikz]{styled bytes}{=\meta{style-selector}}{}
	This probably is by far the most complex setting in this package.
	It allows styling individual bytes based on a selection mechanism.

	In principle, you specify a mapping \texttt{range $\to$ tikz-keys} (where you also can specify an additional predicate).

	Note how the parser and thus the language used here is exactly the same as in the row-selection mechanism (see \cref{selector} and \refCom{hexdumptikzPrint}).
	But this time, you'll be using the \texttt{-> <style>} component as well.

	For examples refer to \cref{extended-example}.
\end{docKey}

\paragraph{Styles}

\begin{docKey}[hexdumptikz]{address node first}{}{style}
	This style is applied to the first address node.

	Note the entire hexdump is drawn based on this first node.
	Thus, you can leverage the \texttt{/tikz/at} key with this style to change the position of the entire hexdump.
\end{docKey}

\begin{docKey}[hexdumptikz]{address node}{}{style}
	This style is applied to every address node.

	Note this style has some initial code in it which is used for the node placement.
	Thus, normally you'll want to use the \texttt{.append style} handler with this style (and avoid overriding the entire style eventhough it is possible).
\end{docKey}

\begin{docKey}[hexdumptikz]{byte node}{}{style}
	This style is applied to every byte node.

	Note this style has some initial code in it which is used for the node placement.
	Thus, normally you'll want to use the \texttt{.append style} handler with this style (and avoid overriding the entire style eventhough it is possible).
\end{docKey}

\subsubsection{Parsing}
The package is designed to work with multiple parsers.
Still so far only one parser exists: \texttt{hd}.

\begin{docKey}[hexdumptikz]{parser}{=\meta{hd}}{initial: hd}
	Allows setting the parser which is to be used.
\end{docKey}

\paragraph{hd}

\begin{docKey}[hexdumptikz]{parser opts hd}{=\meta{keys}}{}
	Sets keys from the \texttt{/hexdumptikz/parser opts/hd} space.

	Can be used to customize settings for the \emph{hd} parser.
\end{docKey}

\begin{docKey}[hexdumptikz/parser opts/hd]{strict byte number per row}{=\meta{bool}}{initial: false, default: true}
	With this enabled, the parser will check that a row does not contain more than \refKey{/hexdumptikz/bytes per row} bytes.
	Else it will raise an error.

	With this disabled, the parsing just stops silently at \refKey{/hexdumptikz/bytes per row} bytes.
\end{docKey}

\begin{docKey}[hexdumptikz/parser opts/hd]{strict hex digits}{=\meta{bool}}{initial: false, default: true}
	Strictly, the bytes do not get interpreted as of now.
	Thus, it does not matter whether valid hex digits are given (they just are read in pairs of two digits).
	This option allows to assert the byte values are valid hex digits (else an error will be raised).
\end{docKey}

\begin{docKey}[hexdumptikz/parser opts/hd]{leading value base}{=\meta{bool}}{initial: false, default: true}
	When enabled, the parser will remove once per row a leading \texttt{0x} from the field representing the byte-values.
	Thus, a format like in the following example can be parsed:
	\begin{verbatim}
		0x000 0x01020304
		0x005 0x05060708
	\end{verbatim}
\end{docKey}

\section{Extended Examples} \label{extended-example}
\subsection{Datafiles used}
\tcbinputlisting{/tcb/docexample,/tcb/documentation listing style,listing only,listing file=dat.hex,title={file: \texttt{dat.hex}}}
\tcbinputlisting{/tcb/docexample,/tcb/documentation listing style,listing only,listing file=dat-small.hex,title={file: \texttt{dat-small.hex}}}

\subsection{Example 1}
\begin{dispExample*}{listing options={language=[LaTeX]TeX},breakable,title={Example 1}}
\begin{tikzpicture}
  \begin{hexdumptikz}[addr len=12,parser=hd,parser opts hd={strict hex digits=true,leading value base=false}]{dat.hex}
    \hexdumptikzPrint[
      styled bytes={
      0x00-0x07 | odd -> {blue},
      0x00-0x07 | even -> {green!50!black},
      0x7fffffffee18-0x7fffffffeeaa | {mod(4,2)} -> {draw=red},
      },
    ]{0,0x8,0x7fffffffee18-0x7fffffffeea8}
    %
    \hexdumptikzLabelBytes[rounded corners]{0x2}{0xa}
  \end{hexdumptikz}
  %
  \begin{hexdumptikz}[
    bytes per row=2,addr len=1,
    address node first/.style={
      at={(hexdumptikz-out-0-end)},right,xshift=4em
    },
  ]{dat-small.hex}
    \hexdumptikzPrint[
      styled bytes={},
    ]{0-4}
    %
    \hexdumptikzLabelBytes[rounded corners]{0x2}{0x6}
  \end{hexdumptikz}
  %
  \hexdumptikzLabelBytesFallback[
    bytes per row=2,addr len=1,rounded corners,tikz=red
  ]{0x2}{0x6}
\end{tikzpicture}
\end{dispExample*}

\subsection{Avoid nodename collisions} \label{nodename-example}

See how in this example the fallback labeling does not really know which hexdump to refer to:
\begin{dispExample*}{listing options={language=[LaTeX]TeX},breakable,title={Colliding nodenames}}
\begin{tikzpicture}
  \begin{hexdumptikz}[bytes per row=2,addr len=1]{dat-small.hex}
    \hexdumptikzPrint{0-4}
    \hexdumptikzLabelBytes[rounded corners]{0x2}{0x6}
  \end{hexdumptikz}
  %
  \begin{hexdumptikz}[
    bytes per row=2,addr len=1,
    address node first/.style={
      at={(hexdumptikz-out-0-end)},right,xshift=4em
    },
  ]{dat-small.hex}
    \hexdumptikzPrint{0-4}
    \hexdumptikzLabelBytes[rounded corners]{0x2}{0x6}
  \end{hexdumptikz}
  %
  \hexdumptikzLabelBytesFallback[
    bytes per row=2,addr len=1,rounded corners,tikz=red
  ]{0x2}{0x6}
\end{tikzpicture}
\end{dispExample*}

You can solve this issue by prefixing the nodenames with \refKey{/hexdumptikz/name prefix} so the nodenames are differentiate between the two dumps:
\begin{dispExample*}{listing options={language=[LaTeX]TeX},breakable,title={Avoid colliding nodenames}}
\begin{tikzpicture}
  \begin{hexdumptikz}[
    name prefix=hd1-,tikz={local bounding box=hd1},
    bytes per row=2,addr len=1
  ]{dat-small.hex}
  \hexdumptikzPrint{0-4}
    \hexdumptikzLabelBytes[rounded corners]{0x2}{0x6}
  \end{hexdumptikz}
  %
  \begin{hexdumptikz}[
    name prefix=hd2-,bytes per row=2,addr len=1,
    address node first/.style={
      at={(hd1-hd1.north east)},below right,xshift=4em
    },
  ]{dat-small.hex}
   \hexdumptikzPrint{0-4}
    \hexdumptikzLabelBytes[rounded corners]{0x2}{0x6}
  \end{hexdumptikz}
  %
  \hexdumptikzLabelBytesFallback[
    name prefix=hd1-,bytes per row=2,addr len=1,rounded corners,tikz=red
  ]{0x2}{0x6}
  %
  \node[above right] at (hd1-hexdumptikz-in-0-end.east) {x1};
  \node[below right] at (hd1-hexdumptikz-out-0-end.east) {y1};
  %
  \node[above right] at (hd2-hexdumptikz-in-0-end.east) {x2};
  \node[below right] at (hd2-hexdumptikz-out-0-end.east) {y2};
\end{tikzpicture}
\end{dispExample*}

Also see how this allows you to specify for fully custom annotations to which hexdump the nodename refers to.

\subsection{Gap nodes} \label{gap-example}
\begin{dispExample*}{listing options={language=[LaTeX]TeX},breakable,title={Gap nodes}}
\begin{tikzpicture}[gap/.style={left,inner xsep=0pt,font=\ttfamily\small}]
  \begin{hexdumptikz}{dat.hex}
    \hexdumptikzPrint{0,0x08,x,0x10,x,x,0x7fffffffee18-0x7fffffffeea8,x}
    \node[gap,blue]           at (hexdumptikz-out-2-gap1) {*};
    \node[gap,green!50!black] at (hexdumptikz-out-3-gap1) {*};
    \node[gap,red]            at (hexdumptikz-0x7fffffffee18-gap2) {*};
  \end{hexdumptikz}
\end{tikzpicture}
\end{dispExample*}

See how the gap-nodenames (and also the generation of the gaps) always are coupled to the succeeding address(node) drawn.
Thus, the last gap-node is not drawn at all.

\section{Implementation}
see \texttt{hexdumptikz-code.pdf}\footnote{eg on \refPkg{hexdumptikz} (CTAN)}

\PrintChanges
\printindex

\end{document}
