% \iffalse % vim: set expandtab: % vim: set shiftwidth=2: % vim: set tabstop=2: % \fi % \iffalse meta-comment % % Copyright (C) 2026 by Lukas Heindl % --------------------------------------------------------------------------- % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3c or later is part of all distributions of LaTeX % version 2008/05/04 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Lukas Heindl. % % This work consists of all files listed in manifest.txt. % % \fi % % \iffalse %<*driver> \ProvidesFile{hexdumptikz-addrcalc.dtx} % %\NeedsTeXFormat{LaTeX2e}[2022-06-01] % %<*driver> \begin{document} \DocInput{\jobname.dtx} \PrintChanges \PrintIndex \end{document} % % \changes{v0.0.0}{2026-05-13}{First draft} % % % \fi % % \iffalse %<*package> %<@@=hexdumptikz_addrcalc> % \fi % % \maketitle % % \begin{abstract} % Defines helpers and variables which are use throughout the whole project. % \end{abstract} % % Identify the package and give the over all version information. % \begin{macrocode} \ProvidesExplPackage {hexdumptikz-addrcalc} {2026-06-20} {1.0.1} {Functionality to work / calculate (limited) with larger addresses} \RequirePackage { hexdumptikz-common } % \end{macrocode} % % \subsection{Helpers} % % \begin{fn}{\@@_byte_index:n} % Leaves the index (column) of a byte on the output % \begin{sideeffects} % \end{sideeffects} % \begin{args} % 1 & \ain & lower digits of an address \\ % - & \ain & \texttt{l\_hexdumptikz\_common\_bytes\_per\_row\_int} \\ % \end{args} % \begin{macrocode} \cs_new:Npn \@@_byte_index:n #1 { \int_mod:nn { \int_from_hex:f { #1 } } { \l_hexdumptikz_common_bytes_per_row_int } } % \end{macrocode} % \end{fn} % % \begin{fn}{\@@_row_lower:n} % Leaves the lower part of the address (\enquote{y-coord}) on the output. % Truncates the input address. % \begin{sideeffects} % \end{sideeffects} % \begin{args} % 1 & \ain & lower digits of an address \\ % - & \ain & \texttt{l\_hexdumptikz\_common\_bytes\_per\_row\_int} \\ % \end{args} % \begin{macrocode} \cs_new:Npn \@@_row_lower:n #1 { \int_to_hex:n { \int_div_truncate:nn { \int_from_hex:f { #1 } } { \l_hexdumptikz_common_bytes_per_row_int } * \l_hexdumptikz_common_bytes_per_row_int } } % \end{macrocode} % \end{fn} % % \subsection{pgfkeys} % Define pgfkeys with is concerned with address calculations % % \begin{var}{\l_@@_hex_digits_calc_int} % size of the address-suffix which is required for calculations % \begin{macrocode} \int_new:N \l_@@_hex_digits_calc_int % \end{macrocode} % \end{var} % % \begin{macrocode} \pgfkeys { /hexdumptikz, % amount of bytes in a row -> needs to be enforced during parsing bytes~per~row/.code = { \int_set:Nn \l_hexdumptikz_common_bytes_per_row_int { \int_abs:n { #1 } } \int_set:Nn \l_@@_hex_digits_calc_int % 16 because addresses must be hexadecimal { ( \l_hexdumptikz_common_bytes_per_row_int + 16 - 1 ) / 16 } \int_compare:nNnT { \l_@@_hex_digits_calc_int } > { 30 } { \msg_warn:nnV { hexdumptikz } { too-many-digits } \l_@@_hex_digits_calc_int } \int_case:nnF { \l_hexdumptikz_common_bytes_per_row_int } { { 1 } { } { 2 } { } { 4 } { } { 8 } { } { 16 } { } } { \int_compare:nNnF { \int_mod:nn { \l_hexdumptikz_common_bytes_per_row_int } { 16 } } = { 0 } { \msg_warning:nnV { hexdumptikz } { weird-num-bytes-per-row } \l_hexdumptikz_common_bytes_per_row_int } } }, bytes~per~row = { 8 }, bytes~per~row/.value~required, % amount of digits the addresses are padded to (without the leading 0x) addr~len/.code = { \int_set:Nn \l_hexdumptikz_common_addr_len_int { \int_abs:n { #1 } } }, addr~len = { 12 }, addr~len/.value~required, } % \end{macrocode} % % \subsection{Variables} % Define variables which are used in the calculation itself. % Note these variables are not used for configuration! % % \begin{var}{\l_@@_addr_tl} % \begin{var}{\l_@@_addr_prefix_tl} % \begin{var}{\l_@@_addr_suffix_tl} % \begin{var}{\l_@@_row_tl} % \begin{macrocode} \tl_new:N \l_@@_addr_tl \tl_new:N \l_@@_addr_prefix_tl \tl_new:N \l_@@_addr_suffix_tl \tl_new:N \l_@@_row_tl % \end{macrocode} % \end{var} % \end{var} % \end{var} % \end{var} % % \begin{var}{\l_@@_addr_len_int} % \begin{var}{\l_@@_addr_prefix_len_int} % \begin{var}{\l_@@_byte_index_int} % \begin{macrocode} \int_new:N \l_@@_addr_len_int % used in calculation != configuration option \int_new:N \l_@@_addr_prefix_len_int \int_new:N \l_@@_byte_index_int % \end{macrocode} % \end{var} % \end{var} % \end{var} % % \subsection{Functions} % % \begin{fn}{\hexdumptikz_address_to_nodename_components:nNN} % Function which splits an address into its two components (row/offset and column) as it corresponds to the hexdump. % \begin{sideeffects} % \sclobber & \sdir & \texttt{l\_@@\_addr\_tl} \\ % \sclobber & \sdir & \texttt{l\_@@\_addr\_len\_int} \\ % \sclobber & \sdir & \texttt{l\_@@\_addr\_prefix\_len\_int} \\ % \sclobber & \sdir & \texttt{l\_@@\_addr\_prefix\_tl} \\ % \sclobber & \sdir & \texttt{l\_@@\_byte\_index\_int} \\ % \sclobber & \sdir & \texttt{l\_@@\_addr\_suffix\_tl} \\ % \sclobber & \sdir & \texttt{l\_@@\_row\_tl} \\ % \end{sideeffects} % \begin{args} % 1 & \ain & tl address to work on \\ % 2 & \aout & output macro for the y-component of the coordinate (tl) \\ % 3 & \aout & output macro for the x-component of the coordinate (tl) \\ % - & \ain & \texttt{l\_@@\_hex\_digits\_calc\_int} \\ % \end{args} % \begin{macrocode} \cs_new_protected:Npn \hexdumptikz_address_to_nodename_components:nNN #1 #2 #3 { % \end{macrocode} % Make a working copy of the address % \begin{macrocode} \tl_set:Ne \l_@@_addr_tl { #1 } % \end{macrocode} % % validate address % \begin{macrocode} \regex_if_match:NVF \c_hexdumptikz_common_hex_regex \l_@@_addr_tl { \msg_critical:nnV { hexdumptikz } { invalid-address } \l_@@_addr_tl } % \end{macrocode} % % Padd the address to avoid issues regarding the indices % \begin{macrocode} \hexdumptikz_common_pad_address:N \l_@@_addr_tl % \end{macrocode} % % strip the leading \texttt{0x} % \begin{macrocode} \regex_replace_once:NnN \c_hexdumptikz_common_leading_hex_base_regex { } \l_@@_addr_tl % \end{macrocode} % % obtain the total length (might be longer than to what was padded) % \begin{macrocode} \int_set:Nn \l_@@_addr_len_int { \tl_count:N \l_@@_addr_tl } % \end{macrocode} % % check length for validity to avoid issues later (should never happen due to the padding) % \begin{macrocode} \int_compare:nNnT { \l_@@_addr_len_int } < { \l_@@_hex_digits_calc_int } { \msg_critical:nnVV { hexdumptikz } { address-too-short } \l_@@_addr_tl \l_@@_hex_digits_calc_int } % \end{macrocode} % % calculate the length the prefix should have % \begin{macrocode} \int_set:Nn \l_@@_addr_prefix_len_int { \l_@@_addr_len_int - \l_@@_hex_digits_calc_int } % \end{macrocode} % % extract the prefix % \begin{macrocode} \tl_set:Ne \l_@@_addr_prefix_tl { \tl_range:Nnn \l_@@_addr_tl { 1 } { \l_@@_addr_prefix_len_int } } % \end{macrocode} % % extract the suffix % \begin{macrocode} \tl_set:Ne \l_@@_addr_suffix_tl { \tl_range:Nnn \l_@@_addr_tl { \l_@@_addr_prefix_len_int + 1 } { \l_@@_addr_len_int } } % \end{macrocode} % % obtain the x-coordinate and (part of) the y-coordinate based on the suffix % \begin{macrocode} \int_set:Nn \l_@@_byte_index_int { \@@_byte_index:n { \l_@@_addr_suffix_tl } } \tl_set:Ne \l_@@_row_tl { \@@_row_lower:n { \l_@@_addr_suffix_tl } } % \end{macrocode} % % padd the y-coordinate suffix to avoid issues when concatenating with the prefix % \begin{macrocode} \hexdumptikz_common_pad_left:Nnn \l_@@_row_tl { \l_@@_hex_digits_calc_int } { 0 } % \end{macrocode} % % Store the two coord components in the output macros % \begin{macrocode} \tl_set:Ne #2 { \l_@@_addr_prefix_tl \l_@@_row_tl } \tl_set:Ne #3 { \int_to_arabic:n { \l_@@_byte_index_int } } } \cs_generate_variant:Nn \hexdumptikz_address_to_nodename_components:nNN { eNN } % \end{macrocode} % \end{fn} % % \begin{fn}{\@@_address_to_nodename:n} % Convert a full address to its nodename as used in the printed hexdump (leaves the nodename on the output) % \begin{sideeffects} % \sclobber & \sdir & \texttt{l\_tmpa\_tl} \\ % \sclobber & \sdir & \texttt{l\_tmpb\_tl} \\ % \end{sideeffects} % \begin{args} % 1 & \ain & tl address to work on \\ % \end{args} % \begin{macrocode} \cs_new:Npn \@@_address_to_nodename:n #1 { \hexdumptikz_address_to_nodename_components:nNN { #1 } \l_tmpa_tl \l_tmpb_tl \l_tmpa_tl \l_tmpb_tl } \cs_generate_variant:Nn \@@_address_to_nodename:n { e } % \end{macrocode} % \end{fn} % % \begin{fn}{\@@_address_to_row:n} % Convert a full address to its row/address-component (leaves the row/address-component on the output) % \begin{sideeffects} % \sclobber & \sdir & \texttt{l\_tmpa\_tl} \\ % \sclobber & \sdir & \texttt{l\_tmpb\_tl} \\ % \end{sideeffects} % \begin{args} % 1 & \ain & tl address to work on \\ % \end{args} % \begin{macrocode} \cs_new:Npn \@@_address_to_row:n #1 { \hexdumptikz_address_to_nodename_components:nNN { #1 } \l_tmpa_tl \l_tmpb_tl \l_tmpa_tl } \cs_generate_variant:Nn \@@_address_to_row:n { e } % \end{macrocode} % \end{fn} % % \begin{fn}{\@@_address_to_col:n} % Convert a full address to its column-component (leaves the column-component on the output) % \begin{sideeffects} % \sclobber & \sdir & \texttt{l\_tmpa\_tl} \\ % \sclobber & \sdir & \texttt{l\_tmpb\_tl} \\ % \end{sideeffects} % \begin{args} % 1 & \ain & tl address to work on \\ % \end{args} % \begin{macrocode} \cs_new:Npn \@@_address_to_col:n #1 { \hexdumptikz_address_to_nodename_components:nNN { #1 } \l_tmpa_tl \l_tmpb_tl \l_tmpb_tl } \cs_generate_variant:Nn \@@_address_to_col:n { e } % \end{macrocode} % \end{fn} % % \iffalse % % \fi % % \Finale