% \iffalse meta-comment % % Copyright (C) 2008 by Scott Pakin % ------------------------------------------------------ % % This file may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3a % 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 2006/05/20 or later. % % \fi % % \iffalse %<*driver> \ProvidesFile{bytefield.dtx} % %\NeedsTeXFormat{LaTeX2e}[1999/12/01] %\ProvidesPackage{bytefield} %<*package> [2005/07/31 v1.2a Network protocol diagrams] % % %<*driver> \documentclass{ltxdoc} \usepackage{textcomp} \usepackage{bytefield} \usepackage{color} \usepackage{rotating} \usepackage{calc} \usepackage{array} \IfFileExists{hyperref.sty}{% \usepackage{hyperref} \definecolor{darkred}{rgb}{0.5,0,0} \definecolor{darkgreen}{rgb}{0,0.3,0} \definecolor{darkblue}{rgb}{0,0,0.5} \definecolor{darkbrown}{rgb}{0.28,0.07,0.07} \hypersetup{% pdftitle={The bytefield package}, pdfauthor={Scott Pakin }, pdfsubject={Protocol diagrams for LaTeX}, pdfkeywords={bits, bytes, bit fields, communication, network protocol diagrams, LaTeX2e, memory maps}, bookmarksopen=true, colorlinks=true, citecolor=darkblue, urlcolor=darkgreen, linkcolor=darkred, menucolor=darkbrown} } \EnableCrossrefs \CodelineIndex \RecordChanges \setcounter{IndexColumns}{2} \begin{document} \DocInput{bytefield.dtx} \PrintChanges \PrintIndex \end{document} % % \fi % % \CheckSum{599} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % % \changes{v1.0}{2000/07/02}{Initial version} % \changes{v1.1}{2002/09/14}{Restructured the \texttt{.dtx} file} % % \GetFileInfo{bytefield.dtx} % % \DoNotIndex{\&,\{,\}} % \DoNotIndex{\addtocounter,\advance} % \DoNotIndex{\begin,\begingroup,\bgroup} % \DoNotIndex{\catcode,\ch@ck,\count,\cr} % \DoNotIndex{\DeclareRobustCommand,\def,\dimen,\dimendef} % \DoNotIndex{\edef,\egroup,\else,\end,\endgroup,\expandafter} % \DoNotIndex{\fi} % \DoNotIndex{\gdef,\global} % \DoNotIndex{\if,\ifnum,\ifx,\ignorespaces,\insc@unt} % \DoNotIndex{\let} % \DoNotIndex{\newbox,\newcounter,\newenvironment,\newif,\newlength} % \DoNotIndex{\newsavebox} % \DoNotIndex{\raisebox,\ratio,\real,\relax,\renewcommand} % \DoNotIndex{\sbox,\setcounter,\setlength,\settowidth,\space,\string} % \DoNotIndex{\the} % \DoNotIndex{\usebox} % \DoNotIndex{\value,\vbox} % \DoNotIndex{\wlog} % \DoNotIndex{\xdef} % % % \title{The \textsf{bytefield} package\thanks{This document % corresponds to \textsf{bytefield}~\fileversion, dated \filedate.}} % \author{Scott Pakin \\ \texttt{scott+bf@pakin.org}} % % \sloppy % \maketitle % % ^^A Define an environment for command/environment delcarations. % \newsavebox{\declbox} % \newenvironment{decl}{^^A % \begin{lrbox}{\declbox}\begin{tabular}{l}}{^^A % \end{tabular}\end{lrbox}^^A % \vspace{3ex}\noindent\hspace*{-3em}\fbox{\usebox{\declbox}}\vspace*{2ex}} % % ^^A Draw a cute smiley face to use within text (classier than ":-)"). % \newcommand{\smileyface}{\raisebox{-2pt}{^^A % \begin{picture}(9,9) % \put(5,5){\circle{9}} % \put(3.5,7){\circle*{2}} % \put(6.6,7){\circle*{2}} % \put(0,0){\makebox(9,3)[t]{\tiny $\,\smile$}} % \end{picture}}} % % ^^A Define an ellipsis that permits a subsequent line break. % \newcommand{\ellipsis}{$\ldots$\linebreak[0]} % % ^^A Define an environment for showing sample bytefield diagrams. % \newenvironment{bffigure}{% % \bigskip % \noindent\hspace*{3em}% % }{% % \bigskip % } % % ^^A Define something like \cs to use within \StopEventually. % \DeclareRobustCommand{\cseq}[1]{\texttt{\string#1}} % % % \begin{abstract} % The \texttt{bytefield} package helps the user create illustrations for % network protocol specifications and anything else that utilizes fields of % data. These illustrations show how the bits and bytes are laid out in a % packet or in memory. % \end{abstract} % % \section{Introduction} % % Network protocols are usually specified in terms of a sequence of bits % and bytes arranged in a field. This is portrayed graphically as % a grid of boxes. Each row in the grid represents one word (frequently, % 32~bits), and each column represents a bit within a word. % The \texttt{bytefield} package makes it easy to typeset these sorts of % figures. % % \texttt{bytefield} lets one draw protocol diagrams that contain: % % \begin{itemize} % \item Words of any arbitrary number of bits % \item Column headers showing bit positions % \item Multiword fields---even non-word-aligned and even if the total % number of bits is not a multiple of the word length % \item Word labels on either the left or right of the figure % \item ``Skipped words'' within fields % \end{itemize} % % Because \texttt{bytefield} draws its figures using only % the \LaTeX{} \texttt{picture} environment, these figures are not % specific to any particular backend, do not require PostScript support, % and do not need support from external programs. Furthermore, unlike an % imported graphic, \texttt{bytefield} pictures can include arbitrary % \LaTeX{} constructs, such as mathematical equations, |\ref|s and % |\cite|s to the surrounding document, and macro calls. % % % \section{Usage} % % \subsection{Basic commands} % % This section explains how to use the \texttt{bytefield} package. % It lists all the exported environments, commands, and variables in % decreasing order of importance. % % \begin{decl} % |\begin{bytefield}| \marg{bit-width} \\ % \meta{fields} \\ % |\end{bytefield}| % \end{decl} % % The top-level environment is called, not surprisingly, % ``|bytefield|''. It takes one (mandatory) argument, which is the % number of bits in each word. One can think of a \texttt{bytefield} as % being analogous to a \texttt{tabular}: words are separated % by~|\\|, and fields within a word are separated by~|&|. % % \begin{decl} % |\wordbox| \oarg{sides} \marg{height} \marg{text} \\ % |\bitbox| \oarg{sides} \marg{width} \marg{text} % \end{decl} % % The two main commands one uses within a \texttt{bytefield} environment % are |\wordbox| and |\bitbox|. The former typesets a field % that is one or more words tall and an entire word wide. % The latter typesets a field that is one or more bits wide and a single % word tall. % % The optional argument, \meta{sides}, is a list of letters % specifying which sides of the field box to draw---|[l]|eft, |[r]|ight, % |[t]|op, and/or |[b]|ottom. The default is ``|lrtb|'' (i.e., all sides % are drawn). \meta{text} is the text to include within the |\wordbox| or % |\bitbox|. It is typeset horizontally centered within a vertically % centered |\parbox|. Hence, words will wrap, and |\\| can % be used to break lines manually. % % The following example shows how to produce a simple 16-bit-wide byte field: % % \begin{verbatim} % \begin{bytefield}{16} % \wordbox{1}{A 16-bit field} \\ % \bitbox{8}{8 bits} & \bitbox{8}{8 more bits} \\ % \wordbox{2}{A 32-bit field. Note that text wraps within the box.} % \end{bytefield} % \end{verbatim} % % The resulting figure looks like this: % % \begin{bffigure} % \begin{bytefield}{16} % \wordbox{1}{A 16-bit field} \\ % \bitbox{8}{8 bits} & \bitbox{8}{8 more bits} \\ % \wordbox{2}{A 32-bit field. Note that text wraps within the box.} % \end{bytefield} % \end{bffigure} % % It is the user's responsibility to ensure that the total % number of bits in each row adds up to the number of bits in a single % word (the mandatory argument to the |bytefield| environment). % % Within a |\wordbox| or |\bitbox|, the \texttt{bytefield} package % defines |\height|, |\depth|, |\totalheight|, and |\width| to the % corresponding dimensions of the box. Section~\ref{sec:tricks} gives an % example of how these lengths may be utilized. % % \begin{decl} % |\bitheader| \oarg{endianness} \marg{bit-positions} % \end{decl} % % To make the figure more readable, it helps to label bit positions across % the top. The |\bitheader| command provides a flexible way to do that. % The optional argument, \meta{endianness} is one of ``|b|'' or ``|l|'' % and specifies whether the bits in each word are numbered in big-endian % style (right to left) or little-endian style (left to right). The default % is little-endian (|l|). % % |\bitheader|'s mandatory argument, \meta{bit-positions}, is a % comma-separated list of bit positions to label. % For example, ``|0,2,4,6,8,10,12,14|'' means to label those bit positions. % The numbers must be listed in increasing order. (Use \meta{endianness} % to display the header in reverse order.) Hyphen-separated ranges are % also valid. For example, ``|0-15|'' means to label all bits from~0 to~15, % inclusive. While not particularly useful, ranges and single numbers can % be intermixed, as in ``|0-3,8,12-15|''. % % The following example shows how |\bitheader| may be used: % % \begin{verbatim} % \begin{bytefield}{32} % \bitheader{0-31} \\ % \bitbox{4}{Four} & \bitbox{8}{Eight} & % \bitbox{16}{Sixteen} & \bitbox{4}{Four} % \end{bytefield} % \end{verbatim} % % The resulting figure looks like this: % % \begin{bffigure} % \begin{bytefield}{32} % \bitheader{0-31} \\ % \bitbox{4}{Four} & \bitbox{8}{Eight} & % \bitbox{16}{Sixteen} & \bitbox{4}{Four} % \end{bytefield} % \end{bffigure} % % % \begin{decl} % |\wordgroupr| \marg{text} \\ % |\endwordgroupr| \\ % \\ % |\wordgroupl| \marg{text} \\ % |\endwordgroupl| % \end{decl} % % When a set of words functions as a single, logical unit, it helps to % group these words together visually. All words defined between % |\wordgroupr| and |\endwordgroupr| will be labeled on the right with % \meta{text}. Similarly, all words defined between % |\wordgroupl| and |\endwordgroupl| will be labeled on the left with % \meta{text}. |\wordgroup|\textit{x} must lie at the beginning of a row % (i.e., right after a |\\|), and |\endwordgroup|\textit{x} must lie right % \emph{before} the end of the row (i.e., right before a |\\|). % % |\wordgroupr|\ellipsis|\endwordgroupr| and % |\wordgroupl|\ellipsis|\endwordgroupl| can overlap each other. % However, they cannot overlap themselves. In other words, % |\wordgroupr|\ellipsis|\wordgroupl|\ellipsis|\endwordgroupr|\ellipsis|\endwordgroupl| % is a valid sequence, but % |\wordgroupr|\ellipsis|\wordgroupr|\ellipsis|\endwordgroupr|\ellipsis|\endwordgroupr| % is not. % % The following example shows how to use |\wordgroupr| and |\endwordgroupr|: % % \begin{verbatim} % \begin{bytefield}{16} % \bitheader{0,7,8,15} \\ % \wordgroupr{Header} % \bitbox{4}{Tag} & \bitbox{12}{Mask} \\ % \bitbox{8}{Source} & \bitbox{8}{Destination} % \endwordgroupr \\ % \wordbox{3}{Data} % \end{bytefield} % \end{verbatim} % % \noindent % Note the justaposition of |\\| to |\wordgroupr| and |\endwordgroupr| % in the above. The resulting figure looks like this: % % \begin{bffigure} % \begin{bytefield}{16} % \bitheader{0,7,8,15} \\ % \wordgroupr{Header} % \bitbox{4}{Tag} & \bitbox{12}{Mask} \\ % \bitbox{8}{Source} & \bitbox{8}{Destination} % \endwordgroupr \\ % \wordbox{3}{Data} % \end{bytefield} % \end{bffigure} % % \noindent % As a more complex example, the following nests left and right labels: % % \begin{verbatim} % \begin{bytefield}{16} % \bitheader{0,7,8,15} \\ % \wordgroupr{Header} % \bitbox{4}{Tag} & \bitbox{12}{Mask} \\ % \wordgroupl{Node IDs} % \bitbox{8}{Source} & \bitbox{8}{Destination} % \endwordgroupl % \endwordgroupr \\ % \wordbox{3}{Data} % \end{bytefield} % \end{verbatim} % % \begin{bffigure} % \begin{bytefield}{16} % \bitheader{0,7,8,15} \\ % \wordgroupr{Header} % \bitbox{4}{Tag} & \bitbox{12}{Mask} \\ % \wordgroupl{Node IDs} % \bitbox{8}{Source} & \bitbox{8}{Destination} % \endwordgroupl % \endwordgroupr \\ % \wordbox{3}{Data} % \end{bytefield} % \end{bffigure} % % \noindent % Again, note the justaposition of |\\| to the various word-grouping % commands in the above. % % \begin{decl} % |\skippedwords| % \end{decl} % % Draw a graphic representing a number of words that are not shown. % |\skippedwords| is intended to work with the \meta{sides} argument % to |\wordbox|. For example: % % \begin{verbatim} % \begin{bytefield}{16} % \wordbox{1}{Some data} \\ % \wordbox[lrt]{1}{Lots of data} \\ % \skippedwords \\ % \wordbox[lrb]{1}{} \\ % \wordbox{2}{More data} % \end{bytefield} % \end{verbatim} % % \begin{bffigure} % \begin{bytefield}{16} % \wordbox{1}{Some data} \\ % \wordbox[lrt]{1}{Lots of data} \\ % \skippedwords \\ % \wordbox[lrb]{1}{} \\ % \wordbox{2}{More data} % \end{bytefield} % \end{bffigure} % % \begin{decl} % |\bitwidth| \\ % |\byteheight| % \end{decl} % % The above variables represent the width of each bit and height of each % byte in the figure. Change them with |\setlength| to adjust the size % of the figure. The default value of |\byteheight| is~|2ex|, and the % default value of |\bitwidth| is the width of ``|{\tiny 99i}|'', % i.e.,~the width of a two-digit number plus a small amount of extra space. % This enables |\bitheader| to show two-digit numbers without overlap. % % \begin{decl} % |\curlyspace| \\ % |\labelspace| % \end{decl} % % |\curlyspace| is the space to insert between the figure and the curly % brace preceding a word group (default: |1ex|). |\labelspace| is the % space to insert between the curly brace and the label (default: |0.5ex|). % Change these with |\setlength| to adjust the spacing. % % \begin{decl} % |\curlyshrinkage| % \end{decl} % % In \TeX/\LaTeX, the height of a curly brace does not include the tips. % Hence, in a word group label, the tips of the curly brace will extend % beyond the height of the word group. |\curlyshrinkage| is an amount by % which to reduce the height of curly braces in labels. It is set to |5pt|, % and it is extremely unlikely that one would ever need to change it. % Nevertheless, it is documented here in case the document is typeset with % a math font containing radically different curly braces from the ones % that come with \TeX/\LaTeX. % % \subsection{Common tricks} % \label{sec:tricks} % % This section shows some clever ways to use \texttt{bytefield}'s commands % to produce some useful effects. % % \paragraph{Odd-sized fields} % To produce a field that is, say, 1\textonehalf{} words long, use a % |\bitbox| for the fractional part and specify appropriate values % for the various \meta{sides} parameters. For instance: % % \begin{verbatim} % \begin{bytefield}{16} % \bitheader{0,7,8,15} \\ % \bitbox{8}{8-bit field} & \bitbox[lrt]{8}{} \\ % \wordbox[lrb]{1}{24-bit field} % \end{bytefield} % \end{verbatim} % % \begin{bffigure} % \begin{bytefield}{16} % \bitheader{0,7,8,15} \\ % \bitbox{8}{8-bit field} & \bitbox[lrt]{8}{} \\ % \wordbox[lrb]{1}{24-bit field} % \end{bytefield} % \end{bffigure} % % \paragraph{Ellipses} % To skip words from the middle of enumerated data, put some |\vdots| % in a |\wordbox| with empty \meta{sides}: % % \begin{verbatim} % \begin{bytefield}{16} % \bitbox{8}{Type} & \bitbox{8}{\# of nodes} \\ % \wordbox{1}{Node~1} \\ % \wordbox{1}{Node~2} \\ % \wordbox[]{1}{$\vdots$ \\[1ex]} \\ % \wordbox{1}{Node~$N$} \\ % \end{bytefield} % \end{verbatim} % % \begin{bffigure} % \begin{bytefield}{16} % \bitbox{8}{Type} & \bitbox{8}{\# of nodes} \\ % \wordbox{1}{Node~1} \\ % \wordbox{1}{Node~2} \\ % \wordbox[]{1}{$\vdots$ \\[1ex]} \\ % \wordbox{1}{Node~$N$} \\ % \end{bytefield} % \end{bffigure} % % \noindent % The extra |1ex| of vertical space helps center the |\vdots| a bit better. % % \paragraph{Narrow fields} % There are a number of options for labeling a narrow field (e.g.,~one % occupying a single bit): % % \newsavebox{\defaultOK} % \begin{lrbox}{\defaultOK} % \begin{bytefield}{8} % \bitbox{1}{OK} & \bitbox{7}{Data} \\ % \end{bytefield} % \end{lrbox} % % \newsavebox{\bitwidthOK} % \begin{lrbox}{\bitwidthOK} % \settowidth{\bitwidth}{OK~}\relax % \begin{bytefield}{8} % \bitbox{1}{OK} & \bitbox{7}{Data} \\ % \end{bytefield} % \end{lrbox} % % \newsavebox{\tinyOK} % \begin{lrbox}{\tinyOK} % \begin{bytefield}{8} % \bitbox{1}{\tiny OK} & \bitbox{7}{Data} \\ % \end{bytefield} % \end{lrbox} % % \newsavebox{\verticalOK} % \begin{lrbox}{\verticalOK} % \begin{bytefield}{8} % \bitbox{1}{\tiny O \\ K} & \bitbox{7}{Data} \\ % \end{bytefield} % \end{lrbox} % % \newsavebox{\rotateOK} % \begin{lrbox}{\rotateOK} % \begin{bytefield}{8} % \bitbox{1}{\rotatebox{90}{\small OK}} & \bitbox{7}{Data} \\ % \end{bytefield} % \end{lrbox} % % \bigskip % % \begin{tabular}{ll} % \emph{Default}: & \raisebox{-4ex}{\usebox{\defaultOK}} \\ % |\settowidth{\bitwidth}{OK~}|: & \raisebox{-4ex}{\usebox{\bitwidthOK}} \\ % |\tiny OK|: & \raisebox{-4ex}{\usebox{\tinyOK}} \\ % |\tiny O \\ K|: & \raisebox{-4ex}{\usebox{\verticalOK}} \\ % |\rotatebox{90}{\small OK}|: & \raisebox{-4ex}{\usebox{\rotateOK}} \\ % \end{tabular} % % \paragraph{Unused bits} % Because |\width| and |\height| are defined within |\bitbox|es (also % |\wordbox|es), we can represent unused bits by filling a |\bitbox| % with a rule of size |\width|~$\times$ |\height|: % % \begin{verbatim} % \begin{bytefield}{32} % \bitheader{0,4,8,12,16,20,24,28} \\ % \bitbox{8}{Tag} & \bitbox{8}{Value} & % \bitbox{4}{\rule{\width}{\height}} & % \bitbox{12}{Mask} \\ % \wordbox{1}{Key} % \end{bytefield} % \end{verbatim} % % \begin{bffigure} % \begin{bytefield}{32} % \bitheader{0,4,8,12,16,20,24,28} \\ % \bitbox{8}{Tag} & \bitbox{8}{Value} & % \bitbox{4}{\rule{\width}{\height}} & % \bitbox{12}{Mask} \\ % \wordbox{1}{Key} % \end{bytefield} % \end{bffigure} % % \noindent % The effect is much better when the \texttt{color} package is used to % draw the unused bits in color. (Gray looks nice.) % % \begin{verbatim} % \definecolor{lightgray}{gray}{0.8} % \begin{bytefield}{32} % \bitheader{0,4,8,12,16,20,24,28} \\ % \bitbox{8}{Tag} & \bitbox{8}{Value} & % \bitbox{4}{\color{lightgray}\rule{\width}{\height}} & % \bitbox{12}{Mask} \\ % \wordbox{1}{Key} % \end{bytefield} % \end{verbatim} % % \definecolor{lightgray}{gray}{0.8} % \begin{bffigure} % \begin{bytefield}{32} % \bitheader{0,4,8,12,16,20,24,28} \\ % \bitbox{8}{Tag} & \bitbox{8}{Value} & % \bitbox{4}{\color{lightgray}\rule{\width}{\height}} & % \bitbox{12}{Mask} \\ % \wordbox{1}{Key} % \end{bytefield} % \end{bffigure} % % \subsection{Not-so-common tricks} % % \paragraph{Colored fields} % A similar approach to that utilized to indicate unused bits can be % applied to coloring an individual bit field. The trick is to use the % \TeX\ |\rlap| primitive to draw a colored box that overlaps whatever % follows it to the right: % % \begin{verbatim} % \begingroup % \small % \newcommand{\colorbitbox}[3]{% % \rlap{\bitbox{#2}{\color{#1}\rule{\width}{\height}}}% % \bitbox{#2}{#3}} % \definecolor{lightcyan}{rgb}{0.84,1,1} % \definecolor{lightgreen}{rgb}{0.64,1,0.71} % \definecolor{lightred}{rgb}{1,0.7,0.71} % % \settowidth{\byteheight}{~Sign~} % \setlength{\bitwidth}{\baselineskip} % \begin{bytefield}{32} % \bitheader[b]{31,23,0} \\ % \colorbitbox{lightcyan}{1}{\rotatebox{90}{Sign}} & % \colorbitbox{lightgreen}{8}{Exponent} & % \colorbitbox{lightred}{23}{Mantissa} \\ % \end{bytefield} % \endgroup % \end{verbatim} % % \begin{center} % \small % \newcommand{\colorbitbox}[3]{% % \rlap{\bitbox{#2}{\color{#1}\rule{\width}{\height}}}^^A % \bitbox{#2}{#3}} % \definecolor{lightcyan}{rgb}{0.84,1,1} % \definecolor{lightgreen}{rgb}{0.64,1,0.71} % \definecolor{lightred}{rgb}{1,0.7,0.71} % % \settowidth{\byteheight}{~Sign~} % \setlength{\bitwidth}{\baselineskip} % \begin{bytefield}{32} % \bitheader[b]{31,23,0} \\ % \colorbitbox{lightcyan}{1}{\rotatebox{90}{Sign}} & % \colorbitbox{lightgreen}{8}{Exponent} & % \colorbitbox{lightred}{23}{Mantissa} \\ % \end{bytefield} % \end{center} % % \paragraph{Memory-map diagrams} % While certainly not the intended purpose of the \texttt{bytefield} % package, one can utilize |\wordbox|es with empty \meta{sides} and % word labels to produce memory-map diagrams: % % \begin{verbatim} % \setlength{\byteheight}{4\baselineskip} % \newcommand{\descbox}[2]{\parbox[c][3.8\baselineskip]{0.95\width}{% % \raggedright #1\vfill #2}} % \begin{bytefield}{32} % \wordgroupr{Partition 4} % \bitbox[]{8}{\texttt{0xFFFFFFFF} \\[2\baselineskip] % \texttt{0xC0000000}} & % \bitbox{24}{\descbox{1\,GB area for VxDs, memory manager, % file system code; shared by all processes.}{Read/writable.}} % \endwordgroupr \\ % \wordgroupr{Partition 3} % \bitbox[]{8}{\texttt{0xBFFFFFFF} \\[2\baselineskip] % \texttt{0x80000000}} & % \bitbox{24}{\descbox{1\,GB area for memory-mapped files, % shared system \textsc{dll}s, file system code; shared by all % processes.}{Read/writable.}} % \endwordgroupr \\ % \wordgroupr{Partition 2} % \bitbox[]{8}{\texttt{0x7FFFFFFF} \\[2\baselineskip] % \texttt{0x00400000}} & % \bitbox{24}{\descbox{$\sim$2\,GB area private to process, % process code, and data.}{Read/writable.}} % \endwordgroupr \\ % \wordgroupr{Partition 1} % \bitbox[]{8}{\texttt{0x003FFFFF} \\[2\baselineskip] % \texttt{0x00001000}} & % \bitbox{24}{\descbox{4\,MB area for MS-DOS and Windows~3.1 % compatibility.}{Read/writable.}} \\ % \bitbox[]{8}{\texttt{0x00000FFF} \\[2\baselineskip] % \texttt{0x00000000}} & % \bitbox{24}{\descbox{4096~byte area for MS-DOS and Windows~3.1 % compatibility.}{Protected---catches \textsc{null} % pointers.}} % \endwordgroupr \\ % \end{verbatim} % % \begin{bffigure} % \setlength{\byteheight}{4\baselineskip} % \newcommand{\descbox}[2]{\parbox[c][3.8\baselineskip]{0.95\width}{% % \raggedright #1\vfill #2}} % \begin{bytefield}{32} % \wordgroupr{Partition 4} % \bitbox[]{8}{\texttt{0xFFFFFFFF} \\[2\baselineskip] % \texttt{0xC0000000}} & % \bitbox{24}{\descbox{1\,GB area for VxDs, memory manager, % file system code; shared by all processes.}{Read/writable.}} % \endwordgroupr \\ % \wordgroupr{Partition 3} % \bitbox[]{8}{\texttt{0xBFFFFFFF} \\[2\baselineskip] % \texttt{0x80000000}} & % \bitbox{24}{\descbox{1\,GB area for memory-mapped files, % shared system \textsc{dll}s, file system code; shared by all % processes.}{Read/writable.}} % \endwordgroupr \\ % \wordgroupr{Partition 2} % \bitbox[]{8}{\texttt{0x7FFFFFFF} \\[2\baselineskip] % \texttt{0x00400000}} & % \bitbox{24}{\descbox{$\sim$2\,GB area private to process, process % code, and data.}{Read/writable.}} % \endwordgroupr \\ % \wordgroupr{Partition 1} % \bitbox[]{8}{\texttt{0x003FFFFF} \\[2\baselineskip] % \texttt{0x00001000}} & % \bitbox{24}{\descbox{4\,MB area for MS-DOS and Windows~3.1 % compatibility.}{Read/writable.}} \\ % \bitbox[]{8}{\texttt{0x00000FFF} \\[2\baselineskip] % \texttt{0x00000000}} & % \bitbox{24}{\descbox{4096~byte area for MS-DOS and Windows~3.1 % compatibility.}{Protected---catches \textsc{null} % pointers.}} % \endwordgroupr \\ % \end{bytefield} % \end{bffigure} % % % \subsection{Putting it all together} % % The following code showcases most of \texttt{bytefield}'s features in a % single figure. % % \begin{verbatim} % \setlength{\byteheight}{2.5\baselineskip} % \begin{bytefield}{32} % \bitheader{0,7,8,15,16,23,24,31} \\ % \wordgroupr{\parbox{6em}{\raggedright These words were taken % verbatim from the TCP header definition (RFC~793).}} % \bitbox{4}{Data offset} & \bitbox{6}{Reserved} & % \bitbox{1}{\tiny U\\R\\G} & \bitbox{1}{\tiny A\\C\\K} & % \bitbox{1}{\tiny P\\S\\H} & \bitbox{1}{\tiny R\\S\\T} & % \bitbox{1}{\tiny S\\Y\\N} & \bitbox{1}{\tiny F\\I\\N} & % \bitbox{16}{Window} \\ % \bitbox{16}{Checksum} & \bitbox{16}{Urgent pointer} % \endwordgroupr \\ % \wordbox[lrt]{1}{Data octets} \\ % \skippedwords \\ % \wordbox[lrb]{1}{} \\ % \wordgroupl{\parbox{6em}{\raggedright Note that we can display, % for example, a misaligned 64-bit value with clever use of the % optional argument to \texttt{\textbackslash wordbox} and % \texttt{\textbackslash bitbox}.}} % \bitbox{8}{Source} & \bitbox{8}{Destination} & % \bitbox[lrt]{16}{} \\ % \wordbox[lr]{1}{Timestamp} \\ % \wordgroupr{\parbox{6em}{\raggedright Why two Length fields? % No particular reason.}} % \bitbox[lrb]{16}{} & \bitbox{16}{Length} % \endwordgroupl \\ % \bitbox{6}{Key} & \bitbox{6}{Value} & \bitbox{4}{Unused} & % \bitbox{16}{Length} % \endwordgroupr \\ % \wordbox{1}{Total number of 16-bit data words that follow this % header word, excluding the subsequent checksum-type value} \\ % \bitbox{16}{Data~1} & \bitbox{16}{Data~2} \\ % \bitbox{16}{Data~3} & \bitbox{16}{Data~4} \\ % \bitbox[]{16}{$\vdots$ \\[1ex]} & % \bitbox[]{16}{$\vdots$ \\[1ex]} \\ % \bitbox{16}{Data~$N-1$} & \bitbox{16}{Data~$N$} \\ % \bitbox{20}{\[ \mbox{A5A5}_{\mbox{\scriptsize H}} \oplus % \left(\sum_{i=1}^N \mbox{Data}_i \right) \bmod 2^{20} \]} & % \bitbox{12}{Command} \\ % \wordbox{2}{64-bit random number} % \end{bytefield} % \end{verbatim} % % \noindent % Figure~\ref{fig:complex-diagram} shows the resulting protocol diagram. % % \begin{figure}[phtb] % \setlength{\byteheight}{2.5\baselineskip} % \begin{bytefield}{32} % \bitheader{0,7,8,15,16,23,24,31} \\ % \wordgroupr{\parbox{6em}{\raggedright These words were taken % verbatim from the TCP header definition (RFC~793).}} % \bitbox{4}{Data offset} & \bitbox{6}{Reserved} & % \bitbox{1}{\tiny U\\R\\G} & \bitbox{1}{\tiny A\\C\\K} & % \bitbox{1}{\tiny P\\S\\H} & \bitbox{1}{\tiny R\\S\\T} & % \bitbox{1}{\tiny S\\Y\\N} & \bitbox{1}{\tiny F\\I\\N} & % \bitbox{16}{Window} \\ % \bitbox{16}{Checksum} & \bitbox{16}{Urgent pointer} % \endwordgroupr \\ % \wordbox[lrt]{1}{Data octets} \\ % \skippedwords \\ % \wordbox[lrb]{1}{} \\ % \wordgroupl{\parbox{6em}{\raggedright Note that we can display, % for example, a misaligned 64-bit value with clever use of the % optional argument to \texttt{\textbackslash wordbox} and % \texttt{\textbackslash bitbox}.}} % \bitbox{8}{Source} & \bitbox{8}{Destination} & \bitbox[lrt]{16}{} \\ % \wordbox[lr]{1}{Timestamp} \\ % \wordgroupr{\parbox{6em}{\raggedright Why two Length fields? % No particular reason.}} % \bitbox[lrb]{16}{} & \bitbox{16}{Length} % \endwordgroupl \\ % \bitbox{6}{Key} & \bitbox{6}{Value} & \bitbox{4}{Unused} & % \bitbox{16}{Length} % \endwordgroupr \\ % \wordbox{1}{Total number of 16-bit data words that follow this % header word, excluding the subsequent checksum-type value} \\ % \bitbox{16}{Data~1} & \bitbox{16}{Data~2} \\ % \bitbox{16}{Data~3} & \bitbox{16}{Data~4} \\ % \bitbox[]{16}{$\vdots$ \\[1ex]} & \bitbox[]{16}{$\vdots$ \\[1ex]} \\ % \bitbox{16}{Data~$N-1$} & \bitbox{16}{Data~$N$} \\ % \bitbox{20}{\[ \mbox{A5A5}_{\mbox{\scriptsize H}} \oplus % \left(\sum_{i=1}^N \mbox{Data}_i \right) \bmod 2^{20} \]} & % \bitbox{12}{Command} \\ % \wordbox{2}{64-bit random number} % \end{bytefield} % \caption{Complex protocol diagram drawn with the \texttt{bytefield} % package} % \label{fig:complex-diagram} % \end{figure} % % % \StopEventually{^^A % % \section{Future work} % % \texttt{bytefield} is my first \LaTeX{} package, and, as such, there % are a number of macros that could probably have been implemented a lot % better. The package should really get a major rewrite. If I were to % do it all over again, I would probably not use an \cseq\ialign\ for the % main \texttt{bytefield} environment. The problem---as I discovered % too late---is that \cseq\begin\ellipsis\cseq\end\ blocks are unable to % cross cells of an \cseq\ialign\ (or \texttt{tabular} environment, for % that matter). % % That said, I'd like the next major release of \texttt{bytefield} to % let the user use \texttt{\cseq\begin\char'173 % wordgroup\char'175[r]}\ellipsis \texttt{\cseq\end\char'173 % wordgroup\char'175} instead of % \cseq\wordgroupr\ellipsis\cseq\endwordgroupr\ and % \texttt{\cseq\begin\char'173 wordgroup\char'175[l]}\ellipsis % \texttt{\cseq\end\char'173 wordgroup\char'175} instead of % \cseq\wordgroupl\ellipsis\cseq\endwordgroupl. That would make the % word-grouping commands a little more \LaTeX-ish. % % Finally, a minor improvement I'd like to make in the package is to % move left, small curly braces closer to the figure. In the following % figure, notice how distant the small curly appears from the figure % body: % % \begin{bffigure} % \setlength{\byteheight}{4ex} % \begin{bytefield}{16} % \wordgroupl{Too distant} % \wordbox{1}{Something} % \endwordgroupl \\ % \wordgroupl{Looks okay} % \wordbox{4}{Something else} % \endwordgroupl % \end{bytefield} % \end{bffigure} % % \noindent % The problem is that the curly braces are left-aligned relative to % each other, while they should be right-aligned. % } % % % \section{Implementation} % % \newcommand{\usermacro}{\marginpar{\vspace*{1ex}{\hspace{18pt}\huge$\star$}\vspace*{-1ex}}} % % This section contains the complete source code for \texttt{bytefield}. % Most users will not get much out of it, but it should be of use to % those who need more precise documentation and those who want to extend % (or debug~\smileyface) the \texttt{bytefield} package. % % In this section, macros marked in the margin with a ``{\Large $\star$}'' % are intended to be called by the user (and were described in the previous % section). All other macros are used only internally by \texttt{bytefield}. % % \begin{macrocode} %<*package> % \end{macrocode} % % % \subsection{Required packages} % % Although |\widthof| and |\heightof| were introduced in June~1998, % te\kern-1.5pt\TeX~2.0---still in widespread use at the time of this % writing (2005)---ships with an earlier |calc.sty| in the |source| % directory. Because a misconfigured system may find the |source| % version of |calc.sty| we explicitly specify a later date when loading % the |calc| package. % \changes{v1.2a}{2005/07/31}{Specified an explicit package date when % loading the \texttt{calc} package to avoid loading an outdated % version. Thanks to Kevin Quick for discovering that outdated versions % of \texttt{calc} are still being included in \TeX{} distributions.} % \begin{macrocode} \RequirePackage{calc}[1998/07/07] % \end{macrocode} % % % \subsection{Utility macros} % % The following macros in this section are used by the box-drawing macros % and the ``skipped words''-drawing macros. % % \begin{macro}{\bf@newdimen} % \changes{v1.1}{2002/09/15}{Bug fix: Added % \texttt{\string\string\string\bf@newdimen} to eliminate ``\texttt{No % room for a new \string\string\string\dimen}'' errors (reported by % Vitaly A. Repin)} % |\newdimen| defines new \meta{dimen}s globally. |\bf@newdimen| % defines them locally. It simply merges \LaTeXe's |\newdimen| and % |\alloc@| macros while omitting |\alloc@|'s ``|\global|'' declaration. % \begin{macrocode} \def\bf@newdimen#1{\advance\count11 by 1 \ch@ck1\insc@unt\dimen% Check room \allocationnumber=\count11 \dimendef#1=\allocationnumber \wlog{\string#1=\string\dimen\the\allocationnumber\space (locally)}} % \end{macrocode} % \end{macro} % % \begin{macro}{\bytefield@height} % \begin{macro}{\ifcounting@words} % When |\ifcounting@words| is \textsc{True}, add the height of the next % \texttt{picture} environment to |\bytefield@height|. We set % |\counting@wordstrue| at the beginning of each word, and % |\counting@wordsfalse| after each |\bitbox|, |\wordbox|, or |\skippedwords| % picture. % \begin{macrocode} \newlength{\bytefield@height} \newif\ifcounting@words % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\inc@bytefield@height} % We have to define a special macro to increment |\bytefield@height| % because the \texttt{calc} package's |\addtolength| macro doesn't seem % to see the global value. So we |\setlength| a temporary (to get % \texttt{calc}'s nice infix features) and |\advance| |\bytefield@height| % by that amount. % \begin{macrocode} \newlength{\bytefield@height@increment} \DeclareRobustCommand{\inc@bytefield@height}[1]{% \setlength{\bytefield@height@increment}{#1}% \global\advance\bytefield@height by \bytefield@height@increment} % \end{macrocode} % \end{macro} % % \subsection{Top-level environment} % % \begin{macro}{bits@wide} % The number of bits in each word (i.e., the argument to the |\bytefield| % environment). % \begin{macrocode} \newcounter{bits@wide} % \end{macrocode} % \end{macro} % % \begin{macro}{\entire@bytefield@picture} % A box containing the entire bytefield. By storing everything in a box % and then typesetting it later (at the |\end{bytefield}|), we can center % the bytefield, put a box around it, and do other operations on the entire % figure. % \begin{macrocode} \newsavebox{\entire@bytefield@picture} % \end{macrocode} % \end{macro} % % \begin{environment}{bytefield} % \usermacro % Environment containing the layout of bits in a sequence of bytes. % This is the main environment defined by the \texttt{bytefield} pacakge. % The argument is the number of bits wide the bytefield should be. % We turn |&| into a space character so the user can think of a % \texttt{bytefield} as being analogous to a \texttt{tabular} environment, % even though we're really setting the bulk of the picture in a single % column. (Row labels go in separate columns, however.) % \begin{macrocode} \newenvironment{bytefield}[1]{% \setcounter{bits@wide}{#1}% \let\old@nl=\\% \let\amp=&% \catcode`\&=10 \openup -1pt \setlength{\bytefield@height}{0pt}% \setlength{\unitlength}{1pt}% \counting@wordstrue \begin{lrbox}{\entire@bytefield@picture}% % \end{macrocode} % \begin{macro}{\\} % We redefine |\\| within the |bytefield| environment to make it aware % of curly braces that surround the protocol diagram. % \begin{macrocode} \renewcommand{\\}{% \amp\show@wordlabelr\cr% \ignorespaces\counting@wordstrue\make@lspace\amp}% % \end{macrocode} % \end{macro} % \begin{macrocode} \vbox\bgroup\ialign\bgroup##\amp##\amp##\cr\amp% }{% \amp\show@wordlabelr\cr\egroup\egroup% \end{lrbox}% \usebox{\entire@bytefield@picture}} % \end{macrocode} % \end{environment} % % \subsection{Box-drawing macros} % % \subsubsection{Drawing (proper)} % % \begin{macro}{\bitwidth} % \usermacro % The width of a single bit. Note that this is wide enough to display a % two-digit number without it running into adjacent numbers. For larger % words, be sure to |\setlength| this larger. % \begin{macrocode} \newlength{\bitwidth} \AtBeginDocument{\settowidth{\bitwidth}{\tiny 99i}} % \end{macrocode} % \end{macro} % % \begin{macro}{\byteheight} % \usermacro % The height of a single byte. % \begin{macrocode} \newlength{\byteheight} \AtBeginDocument{\setlength{\byteheight}{4ex}} % \end{macrocode} % \end{macro} % % \begin{macro}{\units@wide} % \begin{macro}{\units@tall} % Scratch variables for storing the width and height (in points) of % the box we're about to draw. % \begin{macrocode} \newlength{\units@wide} \newlength{\units@tall} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\bitbox} % \usermacro % Put some text (|#3|) in a box that's a given number of bits (|#2|) % wide and one byte tall. % An optional argument (|#1|) specifies which lines to draw---|[l]|eft, % |[r]|ight, |[t]|op, and/or |[b]|ottom (default: |lrtb|). % \begin{macrocode} \DeclareRobustCommand{\bitbox}[3][lrtb]{% \setlength{\units@wide}{\bitwidth * #2}% \parse@bitbox@arg{#1}% \draw@bit@picture{\strip@pt\units@wide}{\strip@pt\byteheight}{#3}} % \end{macrocode} % \end{macro} % % \begin{macro}{\wordbox} % \usermacro % Put some text (|#3|) in a box that's a given number of bytes (|#2|) % tall and one word (|bits@wide| bits) wide. % An optional argument (|#1|) specifies which lines to draw---|[l]|eft, % |[r]|ight, |[t]|op, and/or |[b]|ottom (default: |lrtb|). % \begin{macrocode} \DeclareRobustCommand{\wordbox}[3][lrtb]{% \setlength{\units@wide}{\bitwidth * \value{bits@wide}}% \setlength{\units@tall}{\byteheight * #2}% \parse@bitbox@arg{#1}% \draw@bit@picture{\strip@pt\units@wide}{\strip@pt\units@tall}{#3}} % \end{macrocode} % \end{macro} % % \begin{macro}{\draw@bit@picture} % Put some text (|#3|) in a box that's a given number of units (|#1|) % wide and a given number of units (|#2|) tall. % We format the text with a |\parbox| to enable word-wrapping and explicit % line breaks. In addition, we define |\height|, |\depth|, |\totalheight|, % and |\width| (\`a la |\makebox| and friends), so the user can utilize % those for special effects (e.g., a |\rule| that fills the entire box). % As an added bonus, we define |\widthunits| and |\heightunits|, which % are the width and height of the box in multiples of |\unitlength| % (i.e., |#1| and |#2|, respectively). % \begin{macrocode} \DeclareRobustCommand{\draw@bit@picture}[3]{% \begin{picture}(#1,#2)% % \end{macrocode} % \begin{macro}{\height} % \begin{macro}{\depth} % \begin{macro}{\totalheight} % \begin{macro}{\width} % \begin{macro}{\widthunits} % \begin{macro}{\heightunits} % First, we plot the user's text, with all sorts of useful lengths % predefined. % \begin{macrocode} \put(0,0){\makebox(#1,#2){\parbox[c]{#1\unitlength}{% \bf@newdimen\height \bf@newdimen\depth \bf@newdimen\totalheight \bf@newdimen\width \height=#2\unitlength \depth=0pt% \totalheight=#2\unitlength \width=#1\unitlength \def\widthunits{#1}% \def\heightunits{#2}% \centering #3}}}% % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % Next, we draw each line individually. I suppose we could make a special % case for ``all lines'' and use a |\framebox| above, but the following % works just fine. % \begin{macrocode} \ifbitbox@top \put(0,#2){\line(1,0){#1}} \fi \ifbitbox@bottom \put(0,0){\line(1,0){#1}} \fi \ifbitbox@left \put(0,0){\line(0,1){#2}} \fi \ifbitbox@right \put(#1,0){\line(0,1){#2}} \fi \end{picture}% % \end{macrocode} % Finally, we indicate that we're no longer at the beginning of a word. % The following code structure (albeit with different arguments to % |\inc@bytefield@height|) is repeated in various places throughout this % package. We document it only here, however. % \begin{macrocode} \ifcounting@words \inc@bytefield@height{\unitlength * \real{#2}}% \counting@wordsfalse \fi \ignorespaces} % \end{macrocode} % \end{macro} % % \subsubsection{Parsing arguments} % % The macros in this section are used to parse the optional argument % to |\bitbox| or |\wordbox|, which is some subset of % $\{ |l|, |r|, |t|, |b| \}$. % % \begin{macro}{\ifbitbox@top} % \begin{macro}{\ifbitbox@bottom} % \begin{macro}{\ifbitbox@left} % \begin{macro}{\ifbitbox@right} % These macros are set to \textsc{True} if we're to draw the % corresponding edge on the subsequent |\bitbox| or |\wordbox|. % \begin{macrocode} \newif\ifbitbox@top \newif\ifbitbox@bottom \newif\ifbitbox@left \newif\ifbitbox@right % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\parse@bitbox@arg} % This main parsing macro merely resets the above conditionals and % calls a helper function, |\parse@bitbox@sides|. % \begin{macrocode} \def\parse@bitbox@arg#1{% \bitbox@topfalse \bitbox@bottomfalse \bitbox@leftfalse \bitbox@rightfalse \parse@bitbox@sides#1X} % \end{macrocode} % \end{macro} % % \begin{macro}{\parse@bitbox@sides} % The helper function for |\parse@bitbox@arg| parses a single letter, % sets the appropriate conditional to \textsc{True}, and calls itself % tail-recursively until it sees an ``|X|''. % \begin{macrocode} \def\parse@bitbox@sides#1{% \ifx#1X% \else \ifx#1t% \bitbox@toptrue \else \ifx#1b% \bitbox@bottomtrue \else \ifx#1l% \bitbox@lefttrue \else \ifx#1r% \bitbox@righttrue \fi \fi \fi \fi \expandafter\parse@bitbox@sides \fi} % \end{macrocode} % \end{macro} % % \subsection{Skipped words} % % \begin{macro}{\units@high} % The height of each diagonal line in the |\skippedwords| graphic. % Note that |\units@high|~$=$ |\units@tall|~$-$ \textit{optional argument % to} |\skippedwords|. % \begin{macrocode} \newlength{\units@high} % \end{macrocode} % \end{macro} % % \begin{macro}{\skippedwords} % \usermacro % Output a fancy graphic representing skipped words. The optional argument % is the vertical space between the two diagonal lines (default: |2ex|). % \begin{macrocode} \DeclareRobustCommand{\skippedwords}[1][2ex]{% \setlength{\units@wide}{\bitwidth * \value{bits@wide}}% \setlength{\units@high}{1pt * \ratio{\units@wide}{6.0pt}}% \setlength{\units@tall}{#1 + \units@high}% \edef\num@wide{\strip@pt\units@wide}% \edef\num@tall{\strip@pt\units@tall}% \edef\num@high{\strip@pt\units@high}% \begin{picture}(\num@wide,\num@tall) \put(0,\num@tall){\line(6,-1){\num@wide}} \put(\num@wide,0){\line(-6,1){\num@wide}} \put(0,0){\line(0,1){\num@high}} \put(\num@wide,\num@tall){\line(0,-1){\num@high}} \end{picture}% \ifcounting@words \inc@bytefield@height{\unitlength * \real{\num@tall}}% \counting@wordsfalse \fi} % \end{macrocode} % \end{macro} % % \subsection{Bit-position labels} % % \begin{macro}{\bitheader} % \usermacro % Output a header of numbered bit positions. The optional argument (|#1|) % is ``|l|'' for little-endian (default) or ``|b|'' for big-endian. % The required argument (|#2|) is a list of bit positions to label. % It is composed of comma-separated ranges of numbers, for example, % ``|0-31|'', ``|0,7-8,15-16,23-24,31|'', or even something odd like % ``|0-7,15-23|''. Ranges must be specified in increasing order; use the % optional argument to |\bitheader| to reverse the labels' direction. % \begin{macrocode} \DeclareRobustCommand{\bitheader}[2][l]{% \parse@bitbox@arg{lrtb}% \setlength{\units@wide}{\bitwidth * \value{bits@wide}}% \setlength{\units@tall}{\heightof{\tiny 9}}% \setlength{\units@high}{\units@tall * -1}% \def\bit@endianness{#1}% \begin{picture}(\strip@pt\units@wide,\strip@pt\units@tall)% (0,\strip@pt\units@high) \parse@range@list#2,X, \end{picture}% \ifcounting@words \inc@bytefield@height{\unitlength * \real{\strip@pt\units@tall}}% \counting@wordsfalse \fi \ignorespaces} % \end{macrocode} % \end{macro} % % \begin{macro}{\parse@range@list} % Helper function~\#1 for |\bitheader|---parse a comma-separated list of % ranges, calling |\parse@range| on each range. % \changes{v1.1}{2002/06/24}{Bug fix: Swapped order of arguments to % \texttt{\string\bslash\space ifx} test (suggested by Hans-Joachim % Widmaier)} % \begin{macrocode} \def\parse@range@list#1,{% \ifx X#1 \else \parse@range#1-#1-#1\relax \expandafter\parse@range@list \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\header@xpos} % \begin{macro}{header@val} % \begin{macro}{max@header@val} % Miscellaneous variables used internally by |\parse@range|---$x$ position % of header, current label to output, and maximum label to output ($+ 1$). % \begin{macrocode} \newlength{\header@xpos} \newcounter{header@val} \newcounter{max@header@val} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\parse@range} % Helper function~\#2 for |\bitheader|---parse a hyphen-separated pair % of numbers (or a single number) and display the number at the correct % bit position. % \begin{macrocode} \def\parse@range#1-#2-#3\relax{% \setcounter{header@val}{#1} \setcounter{max@header@val}{#2 + 1} \loop \ifnum\value{header@val}<\value{max@header@val}% \if\bit@endianness b% \setlength{\header@xpos}{% \bitwidth * (\value{bits@wide}-\value{header@val}-1)} \else \setlength{\header@xpos}{\bitwidth * \value{header@val}} \fi \put(\strip@pt\header@xpos,0){% \makebox(\strip@pt\bitwidth,\strip@pt\units@tall){% \tiny \theheader@val}} \addtocounter{header@val}{1} \repeat} % \end{macrocode} % \end{macro} % % \subsection{Word labels} % % \subsubsection{Curly-brace manipulation} % % \begin{macro}{\curlyshrinkage} % \usermacro % Reduce the height of a curly brace by |\curlyshrinkage| so its ends don't % overlap whatever is above or below it. The default value (5\,pt.) was % determined empirically and shouldn't need to be changed. However, % on the off-chance the user employs a math font with very different % curly braces from Computer Modern's, |\curlyshrinkage| can be modified. % \begin{macrocode} \newlength{\curlyshrinkage} \setlength{\curlyshrinkage}{5pt} % \end{macrocode} % \end{macro} % % \begin{macro}{\curlyspace} % \usermacro % \begin{macro}{\labelspace} % \usermacro % Space to insert before a curly brace and before a word label % (i.e., after a curly brace). Because the default values are specified % in terms of $x$~heights, we wait until the |\begin{document}| to set % them, after the default font has been selected. % \begin{macrocode} \newlength{\curlyspace} \AtBeginDocument{\setlength{\curlyspace}{1ex}} \newlength{\labelspace} \AtBeginDocument{\setlength{\labelspace}{0.5ex}} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\curly@box} % Define a box in which to temporarily store formatted curly braces. % \changes{v1.2}{2004/06/14}{Bug fix: Defined % \texttt{\string\string\string\curly@box} globally (suggested by % Stefan Ulrich)} % \begin{macrocode} \newbox{\curly@box} % \end{macrocode} % \end{macro} % % \begin{macro}{\store@rcurly} % \begin{macro}{\curly@height} % \begin{macro}{\half@curly@height} % \begin{macro}{\curly@shift} % Store a ``\}'' that's |#2| tall in box |#1|. % The only unintuitive thing here is that we have to redefine % |\fontdimen22|---axis height---to~0\,pt.\ before typesetting the curly % brace. Otherwise, the brace would be vertically off-center by a few % points. When we're finished, we reset it back to its old value. % \begin{macrocode} \def\store@rcurly#1#2{% \begingroup \bf@newdimen\curly@height% \setlength{\curly@height}{#2 - \curlyshrinkage}% \bf@newdimen\half@curly@height% \setlength{\half@curly@height}{0.5\curly@height}% \bf@newdimen\curly@shift% \setlength{\curly@shift}{\half@curly@height + 0.5\curlyshrinkage}% \global\sbox{#1}{\raisebox{\curly@shift}{% $\xdef\old@axis{\the\fontdimen22\textfont2}$% $\fontdimen22\textfont2=0pt% \left.\vrule height\half@curly@height width 0pt depth\half@curly@height\right\}$% $\fontdimen22\textfont2=\old@axis$}}% \endgroup } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\store@lcurly} % \begin{macro}{\curly@height} % \begin{macro}{\half@curly@height} % \begin{macro}{\curly@shift} % Same as |\store@rcurly|, but using a ``\{'' instead of a ``\}''. % \begin{macrocode} \def\store@lcurly#1#2{% \begingroup \bf@newdimen\curly@height% \setlength{\curly@height}{#2 - \curlyshrinkage}% \bf@newdimen\half@curly@height% \setlength{\half@curly@height}{0.5\curly@height}% \bf@newdimen\curly@shift% \setlength{\curly@shift}{\half@curly@height + 0.5\curlyshrinkage}% \global\sbox{#1}{\raisebox{\curly@shift}{% $\xdef\old@axis{\the\fontdimen22\textfont2}$% $\fontdimen22\textfont2=0pt% \left\{\vrule height\half@curly@height width 0pt depth\half@curly@height\right.$% $\fontdimen22\textfont2=\old@axis$}}% \endgroup } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \subsubsection{Right-side labels} % % \begin{macro}{\show@wordlabelr} % This macro is output in the third column of every row of the % |\ialign|ed bytefield table. It's normally a no-op, but % |\endwordgroupr| defines it to output the word label and then % reset itself to a no-op. % \begin{macrocode} \def\show@wordlabelr{} % \end{macrocode} % \end{macro} % % \begin{macro}{\wordlabelr@start} % \begin{macro}{\wordlabelr@end} % The starting and ending height (in points) of the set of rows to be % labelled on the right. % \begin{macrocode} \newlength{\wordlabelr@start} \newlength{\wordlabelr@end} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\wordgroupr} % \usermacro % \begin{macro}{\endwordgroupr} % \usermacro % Label the words defined between |\wordgroupr| and |\endwordgroupr| % on the right side of the figure. % The argument is the text of the label. The label is typeset to the % right of a large curly brace, which groups the words together. % \begin{macrocode} \newenvironment{wordgroupr}[1]{% % \end{macrocode} % \begin{macro}{\wordlabelr@start} % \begin{macro}{\wordlabelr@text} % \begin{macro}{\wordlabelr@end} % |\wordgroupr| merely stores the starting height in |\wordlabelr@start| % and the user-supplied text in |\wordlabelr@text|. |\endwordgroupr| % does most of the work. % \begin{macrocode} \global\wordlabelr@start=\bytefield@height \gdef\wordlabelr@text{#1}% \ignorespaces% }{% \global\wordlabelr@end=\bytefield@height % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \begin{macro}{\show@wordlabelr} % Redefine |\show@wordlabelr| to output |\curlyspace| space, followed by % a large curly brace (in |\curlybox|), followed by |\labelspace| space, % followed by the user's text (previously recorded in |\wordlabelr@text|). % We typeset |\wordlabelr@text| within a |tabular| environment, so % \LaTeX\ will calculate its width automatically. % \begin{macrocode} \gdef\show@wordlabelr{% \sbox{\word@label@box}{% \begin{tabular}[b]{@{}l@{}}\wordlabelr@text\end{tabular}}% \settowidth{\label@box@width}{\usebox{\word@label@box}}% \setlength{\label@box@height}{\wordlabelr@end-\wordlabelr@start}% \store@rcurly{\curly@box}{\label@box@height}% \bf@newdimen\total@box@width% \setlength{\total@box@width}{% \curlyspace + \widthof{\usebox{\curly@box}} + \labelspace + \label@box@width}% \begin{picture}(\strip@pt\total@box@width,0) \put(0,0){% \hspace*{\curlyspace}% \usebox{\curly@box}% \hspace*{\labelspace}% \makebox(\strip@pt\label@box@width,\strip@pt\label@box@height){% \usebox{\word@label@box}}} \end{picture}% % \end{macrocode} % The last thing |\show@wordlabelr| does is redefine itself back to a no-op. % \begin{macrocode} \gdef\show@wordlabelr{}}% \ignorespaces} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \subsubsection{Left-side labels} % % \begin{macro}{\wordlabell@start} % \begin{macro}{\wordlabell@end} % The starting and ending height (in points) of the set of rows to be % labelled on the left. % \begin{macrocode} \newlength{\wordlabell@start} \newlength{\wordlabell@end} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\total@box@width} % The total width of the next label to typeset on the left of the figure, % that is, the aggregate width of the text box, curly brace, and spaces % on either side of the curly brace. % \begin{macrocode} \newlength{\total@lbox@width} % \end{macrocode} % \end{macro} % % \begin{macro}{\make@lspace} % This macro is output in the first column of every row of the % |\ialign|ed bytefield table. It's normally a no-op, but % |\wordgroupl| defines it to output enough space for the next word % label and then reset itself to a no-op. % \begin{macrocode} \gdef\make@lspace{} % \end{macrocode} % \end{macro} % % \begin{macro}{\wordgroupl} % \usermacro % \begin{macro}{\endwordgroupl} % \usermacro % Same as |\wordgroupr| and |\endwordgroupr|, but put the label on the left. % However, the following code is not symmetric to that of |\wordgroupr| % and |\endwordgroupr|. The problem is that we encounter |\wordgroupl| % after entering the second (i.e., figure) column, which doesn't give us % a chance to reserve space in the first (i.e., left label) column. % When we reach the |\endwordgroupl|, we know the height of the group of % words we wish to label. However, if we try to label the words in the % subsequent first column, we won't know the vertical offset from the % ``cursor'' at which to start drawing the label, because we can't know % the height of the subsequent row until we reach the second % column.\footnote{Question: Is there a way to push the label up to the % \emph{top} of the subsequent row, perhaps with % \texttt{\textbackslash vfill}?} % % Our solution is to allocate space for the box the next time we enter a % first column. As long as space is eventually allocated, the column % will expand to fit that space. |\endwordgroupl| outputs the label % immediately. Even though |\endwordgroupl| is called at the end % of the \emph{second} column, it |\put|s the label at a sufficiently % negative $x$ location for it to overlap the first column. Because there % will eventually be enough space to accomodate the label, we know that % the label won't overlap the figure or extend beyond the figure boundaries. % \begin{macrocode} \newenvironment{wordgroupl}[1]{% % \end{macrocode} % \begin{macro}{\wordlabell@start} % \begin{macro}{\wordlabell@text} % First, we store the starting height and label text, which are needed % by |\endwordgroupl|. % \begin{macrocode} \global\wordlabell@start=\bytefield@height \gdef\wordlabell@text{#1}% % \end{macrocode} % \end{macro} % \end{macro} % Next, we typeset a draft version of the label into |\word@label@box|, % which we measure (into |\total@lbox@width|) and then discard. % We can't typeset the final version of the label until we reach the % |\endwordgroupl|, because that's when we learn the height of the % word group. Without knowing the height of the word group, we don't % how how big to make the curly brace. In the scratch version, we make % the curly brace 5\,cm.~tall. This should be more than large enough to % reach the maximum curly-brace width, which is all we really care about % at this point. % \begin{macrocode} \sbox{\word@label@box}{% \begin{tabular}[b]{@{}l@{}}\wordlabell@text\end{tabular}}% \settowidth{\label@box@width}{\usebox{\word@label@box}}% \store@lcurly{\curly@box}{5cm}% \setlength{\total@lbox@width}{% \curlyspace + \widthof{\usebox{\curly@box}} + \labelspace + \label@box@width}% \global\total@lbox@width=\total@lbox@width % \end{macrocode} % Now we know how wide the box is going to be (unless, of course, % the user is using some weird math font that scales the width of a curly % brace proportionally to its height). So we redefine |\make@lspace| to % output |\total@lbox@width|'s worth of space and then redefine itself % back to a no-op. % \begin{macrocode} \gdef\make@lspace{% \hspace*{\total@lbox@width}% \gdef\make@lspace{}}% \ignorespaces% }{% % \end{macrocode} % |\endwordgroupl| is comparatively straightforward. We calculate the % final height of the word group, and then output the label text, followed % by |\labelspace| space, followed by a curly brace (now that we know how % tall it's supposed to be), followed by |\curlyspace| space. The trick, % as described earlier, is that we typeset the entire label in the second % column, but in a $0 \times 0$ |picture| environment and with a negative % horizontal offset (|\starting@point|), thereby making it overlap the % first column. % \begin{macrocode} \global\wordlabell@end=\bytefield@height \bf@newdimen\starting@point \setlength{\starting@point}{% -\total@lbox@width - \bitwidth*\value{bits@wide}}% \sbox{\word@label@box}{% \begin{tabular}[b]{@{}l@{}}\wordlabell@text\end{tabular}}% \settowidth{\label@box@width}{\usebox{\word@label@box}}% \setlength{\label@box@height}{\wordlabell@end-\wordlabell@start}% \store@lcurly{\curly@box}{\label@box@height}% \begin{picture}(0,0) \put(\strip@pt\starting@point,0){% \makebox(\strip@pt\label@box@width,\strip@pt\label@box@height){% \usebox{\word@label@box}}% \hspace*{\labelspace}% \usebox{\curly@box}% \hspace*{\curlyspace}} \end{picture}% \ignorespaces} % \end{macrocode} % \end{macro} % \end{macro} % % \subsubsection{Scratch space} % % \begin{macro}{\label@box@width} % \begin{macro}{\label@box@height} % \begin{macro}{\word@label@box} % Scratch storage for the width, height, and contents of the word label % we're about to output. % \begin{macrocode} \newlength{\label@box@width} \newlength{\label@box@height} \newsavebox{\word@label@box} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \Finale \endinput