1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
|
% \iffalse
%
% bitpattern.dtx
%
% This file is part of the bitpattern, a LaTeX package to typeset bit
% pattern diagrams.
% https://bitbucket.org/bourguet/bitpattern
%
% Copyright 2005--2015 Jean-Marc Bourguet
%
% This program is provided under the terms of the LaTeX Project Public
% License distributed from CTAN archives in directory
% macros/latex/base/lppl.txt.
%
% Run LaTeX on the file 'bitpattern.ins' to get a .sty to place in
% your tex hierarchy.
%
% Run LaTeX on the file 'bitpattern.dtx' to get a manual. If the
% |\OnlyDescription| command is commented out, you get commented
% sources in the manual, else you get only the user's manual part.
%
%<*dtx>
\ProvidesFile{bitpattern.dtx}
%</dtx>
% \fi
%
%% \CheckSum{412}
%
% \title{Bit pattern diagrams}
% \author{Jean-Marc Bourguet\\
% \texttt{jm@bourguet.org}}
%
% \maketitle
% \begin{abstract}
% The |bitpattern| package is designed to typeset bit patterns as
% they may appear in description of data format, hardware registers
% or transmission protocols. It covers thus more or less the same
% application domain as the package |register| and is somewhat
% related to |bytefield|.
%
% Comparared to |register| the formating is more compact, the
% syntax less verbose and |bitpattern| allows to choose between big
% endian and little endian bit numbering. But |bitpattern| is less
% well adapted to the use of long names for the fields and has no
% provision for a reset value. |bytefield| is more adequate to
% describe multi-word protocols, while |bitpattern| is more adapted
% to describe the intra-word structure of a single word.
% \end{abstract}
%
% \iffalse
%<*driver>
\documentclass{ltxdoc}
\RequirePackage[numberFieldsOnce,bigEndian,numberBitsAbove]%
{bitpattern}
\renewcommand\descriptionlabel[1]{\hspace{\labelsep}\texttt{#1}}
%\OnlyDescription
\begin{document}
\DocInput{bitpattern.dtx}
\end{document}
%</driver>
% \fi
% \section{Examples}
%
% We'll the instruction formats of two processors to describe the
% features of |bitpattern|, the DEC PDP-10 and the Intel 8080.
%
% The PDP-10 was a word-adressable 36-bit computer, something quite
% strange to our eyes (it's most familiar feature is probably the
% fact that it uses 2's complement) and the reason for which I've
% chosen it is that it was the computer on which \TeX{} was first
% implemented.
%
% The PDP-10 has two instruction formats, one used for most of the
% instructions:
%
% \noindent\bitpattern{Op}[9]{AC}[4]IX[4]Y[18]/
%
% \noindent and the other used for IO instructions:
%
% \noindent\bitpattern[numberBitsBelow]{111}[3]{Dev}[7]{IOP}[3]IX[4]Y[18]/
%
% As well at putting the bit numbers above or below the field
% description, |bitpattern| allows to number all the bits:
%
% \noindent\bitpattern[numberAllBits]{Op}[9]{AC}[4]IX[4]Y[18]/
%
% \noindent or only at the start and end of a field:
%
% \noindent\bitpattern[numberBitsBelow,numberFieldsTwice]{111}[3]{Dev}[7]{IOP}[3]IX[4]Y[18]/
%
% Having a long field like \emph{Y} here may take more place than
% wanted. |bitpattern| allows to reduce that:
%
% \noindent\bitpattern{Op}[9]{AC}[4]IX[4]Y[18][9]/
%
% Other ways to avoid overstepping in the margin include splitting
% the pattern in two:
%
% \noindent\bitpattern[bitWidth=1.5em,numberAllBits]{Op}[9]{AC}[4]IX[4]/ \\
% \hspace*{1pt plus 1filll}\bitpattern[numberBitsBelow,startBit=18,bitWidth=1.5em,numberAllBits] Y[18]/
%
% \noindent and reducing the width of the cells:
%
% {\centering\bitpattern[bitWidth=0.8em]{Op}[9]{AC}[4]IX[4]Y[18]/ \par}
%
% The PDP-10 numbered its bits in the big endian way. That's not the
% case of the Intel 8080. The 8080 was an 8-bit computer. Trying to
% pack instructions in 8-bit forces to use a lot of formats. One of
% them was used for the move instruction, and let's take that
% opportunity to start and compact the layout of the bit field by
% changing the format of the bit numbers and the field descriptions:
%
% \renewcommand\bpFormatBitNumber[1]{{\tiny\ttfamily\emph{\strut#1}}}
% \renewcommand\bpFormatField[1]{{\scriptsize\ttfamily\strut#1}}
% {\centering\bitpattern[littleEndian,startBit=7,numberBitsBelow]{01}[2]{D}[3]{S}[3]/\par}
%
%
% \bpSetTickHeight{1pt}
% \newlength{\bpDocExampleHeight}
% \settoheight{\bpDocExampleHeight}{{\scriptsize\ttfamily 0}}
% \newcommand{\bpDocExampleStrut}{\rule{0pt}{\bpDocExampleHeight}}
% \renewcommand\bpFormatField[1]{{\scriptsize\ttfamily\bpDocExampleStrut #1}}
%
% After that it is possible to still be more compact by removing the
% numbers, reducing the height of the ticks and avoiding the provide
% the space for ascender and descenders in the field name (obviously
% that is possible only with convenient field names). When that's
% done, you can put a bit pattern in a paragraph without disturbing
% it too much, like this
% \bitpattern[noBitNumbers,littleEndian,startBit=7]{01}[2]{D}[3]{S}[3]/.
% With some text afterwards to see how the next line is handled. The
% result seems quite readable, remark for instance that the baseline
% of the field description is aligned with the baseline of the line
% in which it is included.
%
% \section{Interface}
%
% \subsection{\cmd{\bitpattern}}
%
% \DescribeMacro{\bitpattern} The |\bitpattern| macro is the macro
% which formats the patterns.
%
% \begin{quote}
% \cmd{\bitpattern}\oarg{format}\marg{name}\oarg{size}\oarg{width}\dots\verb+/+
% \end{quote}
%
% The first optional argument allows to control how the formatting is
% made and is the combination of the following keys:
% \begin{description}
% \item[littleEndian] indicates that bit numbering is little endian,
% that is the leftward bit has the biggest number;
% \item[bigEndian] indicates that bit numbering is big endian, that
% is the leftward bit has the lowest number;
% \item[numberBitsAbove] indicates that the bit numbers should be put
% above the fields;
% \item[numberBitsBelow] indicates that the bit numbers should be put
% below the fields;
% \item[noBitNumbers] indicates that there should be no bit numbers;
% \item[numberFieldsOnce] indicates that the fields should have
% only one bit number;
% \item[numberFieldsTwice] indicates that the fields should have
% two bit numbers;
% \item[numberAllBits] indicates that the fields shouldn't have a bit
% number indication;
% \item[startBit=X] indicates that the number for the leftmost bit
% should be $X$;
% \item[bitWidth=dimen] indicates that the size taken by a bit should
% be \emph{dimen};
% \item[tickHeight=dimen] indicates that the size taken by the small
% ticks marking the bits should be \emph{dimen}.
% \end{description}
%
% After the optional argument comes the description of the
% fields. Each field is described by its name as a mandatory argument
% (which does not have to be included in braces if it takes one
% character) followed by two optional arguments giving the size of
% the field (1 if omitted) and the width it should take (the same as
% its size if it is not specified).
%
% Field descriptions are ended by a \verb+/+.
%
% \subsection{Package options}
%
% The package |bitpattern| accept the following options which set up
% the default values for the formatting controls:
% \begin{description}
% \item[littleEndian] indicates that the default for bit numbering is
% little endian, that is the leftward bit has the biggest number;
% \item[bigEndian] indicates that the default for bit numbering is
% big endian, that is the leftward bit has the lowest number;
% \item[numberBitsAbove] indicates that by default the bit numbers
% should be put above the fields;
% \item[numberBitsBelow] indicates that by default the bit numbers
% should be put below the fields;
% \item[noBitNumbers] indicates that by default there should be no
% bit numbers;
% \item[numberFieldsOnce] indicates that by default the fields
% should have only one bit number;
% \item[numberFieldsTwice] indicates that by default the fields
% should have two bit numbers;
% \item[numberAllBits] indicates that by default the fields shouldn't
% have a bit number indication.
% \end{description}
%
% \subsection{Commands controlling the format}
%
% \DescribeMacro{\bpLittleEndian} |\bpLittleEndian| changes the
% default bit numbering to little endian.
%
% \DescribeMacro{\bpBigEndian} |\bpBigEndian| changes the default bit
% numbering to little endian.
%
% \DescribeMacro{\bpNumberBitsAbove} |\bpNumberBitsAbove| changes the
% default to having the numbering above the fields.
%
% \DescribeMacro{\bpNumberBitsBelow} |\bpNumberBitsBelow| changes the
% default to having the numbering below the fields.
%
% \DescribeMacro{\bpNoBitNumbers} |\bpNoBitNumbers| changes the
% default to having no numbering.
%
% \DescribeMacro{\bpNumberFieldsOnce} |\bpNumberFieldsOnce| changes the
% default to having the numbering done once per field.
%
% \DescribeMacro{\bpNumberFieldsTwice} |\bpNumberFieldsTwice| changes
% the default to having the numbering done twice per field.
%
% \DescribeMacro{\bpNumberAllBits} |\bpNumberAllBits| changes the
% default to having the numbering done for all bits of a field.
%
% \begin{quote}
% \cmd{\bpStartAtBit}\marg{number}
% \end{quote}
%
% \DescribeMacro{\bpStartAtBit} |\bpStartAtBit| gives the default bit
% number of the leftmost bit.
%
% \begin{quote}
% \cmd{\bpSetBitWidth}\marg{length}
% \end{quote}
%
% \DescribeMacro{\bpSetBitWidth} |\bpSetBitWidth| gives the default
% bit width
%
% \begin{quote}
% \cmd{\bpSetTickHeight}\marg{length}
% \end{quote}
%
% \DescribeMacro{\bpSetTickHeight} |\bpSetTickHeight| gives the
% default height for the ticks marking the bits in a multi-bit field.
%
% \DescribeMacro{\bpFormatField} |\bpFormatField| is a one argument
% macro used fo format the field. It can be replaced. Care should
% be taken to format all the fields with the same height, so putting
% a |\strut| in the replacement is probably in order.
%
% \DescribeMacro{\bpFormatBitNumber} |\bpFormatBitNumber| is a one
% argument macro used fo format the bit numbers. It can be replaced.
% Care should be taken to format all the bit numbers with the same
% height, so putting a |\strut| in the replacement is perhaps in
% order.
%
% \section{Examples revisited}
%
% \bpSetTickHeight{2pt}
% \renewcommand\bpFormatField[1]{\strut\emph{#1}}
% \renewcommand\bpFormatBitNumber[1]{{\tiny\sffamily\strut #1}}
% |bitpattern| was loaded by:
% \begin{verbatim}
% \RequirePackage[numberFieldsOnce,bigEndian,numberBitsAbove]{bitpattern}
% \end{verbatim}
% \smallskip
% \noindent\bitpattern{Op}[9]{AC}[4]IX[4]Y[18]/
% \begin{verbatim}
% \bitpattern{Op}[9]{AC}[4]IX[4]Y[18]/
% \end{verbatim}
%
% \smallskip
% \noindent\bitpattern[numberBitsBelow]{111}[3]{Dev}[7]{IOP}[3]IX[4]Y[18]/
% \begin{verbatim}
% \bitpattern[numberBitsBelow]{111}[3]{Dev}[7]{IOP}[3]IX[4]Y[18]/
% \end{verbatim}
%
% \smallskip
% \noindent\bitpattern[numberAllBits]{Op}[9]{AC}[4]IX[4]Y[18]/
% \begin{verbatim}
% \bitpattern[numberAllBits]{Op}[9]{AC}[4]IX[4]Y[18]/
% \end{verbatim}
%
% \smallskip
% \noindent\bitpattern[numberBitsBelow,numberFieldsTwice]{111}[3]{Dev}[7]{IOP}[3]IX[4]Y[18]/
% \begin{verbatim}
% \bitpattern[numberBitsBelow,numberFieldsTwice]%
% {111}[3]{Dev}[7]{IOP}[3]IX[4]Y[18]/
% \end{verbatim}
%
% \smallskip
% \noindent\bitpattern[numberBitsBelow,numberFieldsTwice]111{Dev}[7]{IOP}[3]IX[4]Y[18]/
% \begin{verbatim}
% \bitpattern[numberBitsBelow,numberFieldsTwice]%
% 111{Dev}[7]{IOP}[3]IX[4]Y[18]/
% \end{verbatim}
%
% \smallskip
% \noindent\bitpattern{Op}[9]{AC}[4]IX[4]Y[18][9]/
% \begin{verbatim}
% \bitpattern{Op}[9]{AC}[4]IX[4]Y[18][9]/
% \end{verbatim}
%
% \smallskip
% \noindent\bitpattern[bitWidth=1.5em,numberAllBits]{Op}[9]{AC}[4]IX[4]/ \\
% \hspace*{1pt plus 1filll}\bitpattern[numberBitsBelow,startBit=18,bitWidth=1.5em,numberAllBits] Y[18]/
%
% This wasn't composed directly by as two bit patterns, using the
% possibility of specifying a starting bit. To put a nicer touch,
% the width of the cells has been expanded (the default width had an
% overlap so small that going into the margin is a better format),
% and the numbering was put above the pattern for the first and below
% for the second.
% \begin{verbatim}
% \noindent\bitpattern[bitWidth=1.5em,numberAllBits]{Op}[9]{AC}[4]IX[4]/ \\
% \hspace*{1pt plus 1filll}
% \bitpattern[numberBitsBelow,startBit=18,bitWidth=1.5em,numberAllBits] Y[18]/
% \end{verbatim}
%
% \smallskip
% {\centering\bitpattern[bitWidth=0.8em]{Op}[9]{AC}[4]IX[4]Y[18]/ \par}
% \begin{verbatim}
% {\centering\bitpattern[bitWidth=0.8em]{Op}[9]{AC}[4]IX[4]Y[18]/ \par}
% \end{verbatim}
%
% \smallskip
% \renewcommand\bpFormatBitNumber[1]{{\tiny\ttfamily\emph{\strut#1}}}
% \renewcommand\bpFormatField[1]{{\scriptsize\ttfamily\strut#1}}
% {\centering\bitpattern[littleEndian,startBit=7,numberBitsBelow]{01}[2]{D}[3]{S}[3]/\par}
% \begin{verbatim}
% \renewcommand\bpFormatBitNumber[1]{{\tiny\ttfamily\emph{\strut#1}}}
% \renewcommand\bpFormatField[1]{{\scriptsize\ttfamily\strut#1}}
% {\centering\bitpattern[littleEndian,startBit=7,numberBitsBelow]{01}[2]{D}[3]{S}[3]/\par}
% \end{verbatim}
%
% \smallskip
% \bpSetTickHeight{1pt}
% \renewcommand\bpFormatField[1]{{\scriptsize\ttfamily\bpDocExampleStrut #1}}
% {\centering\bitpattern[noBitNumbers,littleEndian,startBit=7]{01}[2]{D}[3]{S}[3]/\par}
% This example was made to be as compact as possible. Expanding the
% strut a little more vertically wouldn't be unwise.
% \begin{verbatim}
% \bpSetTickHeight{1pt}
% \newlength{\bpDocExampleHeight}
% \settoheight{\bpDocExampleHeight}{\scriptsize\ttfamily 0}
% \newcommand{\bpDocExampleStrut}{\rule{0pt}{\bpDocExampleHeight}}
% \renewcommand\bpFormatBitNumber[1]{{\tiny\ttfamily\emph{\strut#1}}}
% \renewcommand\bpFormatField[1]{{\scriptsize\ttfamily\bpDocExampleStrut #1}}
% {\centering\bitpattern[noBitNumbers,littleEndian,startBit=7]{01}[2]{D}[3]{S}[3]/\par}
% \end{verbatim}
% Note that if you put a descender, the formatting is then disturbed:
% {\centering\bitpattern[noBitNumbers,littleEndian,startBit=7]{01}[2]{D}[3]{p}[3]/\par}
%
% \smallskip
% It is to be noted that usually one does not change the formatting
% for every pattern, so setting the optional argument of
% \cs{bitpattern} is rarely used.
% \StopEventually{}
%
% \newpage
% \section{Implementation}
%
% First let's have a standard preamble and indicates the package we
% requires.
%
% \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{bitpattern}[2015/12/11 bit pattern diagrams]
\RequirePackage{keyval}
\RequirePackage{calc}
\RequirePackage{multido}
% \end{macrocode}
% Now we'll declare some new |\if| commands which will be set to
% describe the options.
% \begin{macrocode}
\newif\ifbp@NumberBitsAbove
\newif\ifbp@NumberBitsBelow
\newif\ifbp@HasBitNumbers
\newif\ifbp@NumberFieldTwice
\newif\ifbp@NumberAllBits
\newif\ifbp@NumberBitsBigEndian
% \end{macrocode}
% We need a counter to store the starting bit number. We are not
% using the \LaTeX{} way because we want to use it locally and not
% globally.
% \begin{macrocode}
\newcount\bp@StartBit
% \end{macrocode}
% \LaTeX{} length behaves are needed, so use them.
% \begin{macrocode}
\newlength{\bp@BitWidth}
\newlength{\bp@TickHeight}
% \end{macrocode}
%
% First the user level macros allowing to change the default. They
% are easy, the just set the |\if|.
% \begin{macrocode}
\newcommand\bpLittleEndian
{\bp@NumberBitsBigEndianfalse}
\newcommand\bpBigEndian
{\bp@NumberBitsBigEndiantrue}
\newcommand\bpNumberBitsAbove
{\bp@NumberBitsAbovetrue
\bp@NumberBitsBelowfalse}
\newcommand\bpNumberBitsBelow
{\bp@NumberBitsAbovefalse
\bp@NumberBitsBelowtrue}
\newcommand\bpNoBitNumbers
{\bp@HasBitNumbersfalse}
\newcommand\bpNumberFieldsOnce
{\bp@HasBitNumberstrue
\bp@NumberFieldTwicefalse
\bp@NumberAllBitsfalse}
\newcommand\bpNumberFieldsTwice
{\bp@HasBitNumberstrue
\bp@NumberFieldTwicetrue
\bp@NumberAllBitsfalse}
\newcommand\bpNumberAllBits
{\bp@HasBitNumberstrue
\bp@NumberFieldTwicetrue
\bp@NumberAllBitstrue}
% \end{macrocode}
%
% About as easy, macros setting the counter and the lengths.
% \begin{macrocode}
\newcommand\bpStartAtBit[1]{\bp@StartBit=#1}
\newcommand\bpSetBitWidth[1]{\setlength{\bp@BitWidth}{#1}}
\newcommand\bpSetTickHeight[1]{\setlength{\bp@TickHeight}{#1}}
% \end{macrocode}
%
% Now we set up the keyval handling
% \begin{macrocode}
\define@key{bitpattern}{littleEndian}[true]{\bpLittleEndian}
\define@key{bitpattern}{bigEndian}[true]{\bpBigEndian}
\define@key{bitpattern}{numberBitsAbove}[true]{\bpNumberBitsAbove}
\define@key{bitpattern}{numberBitsBelow}[true]{\bpNumberBitsBelow}
\define@key{bitpattern}{noBitNumbers}[true]{\bpNoBitNumbers}
\define@key{bitpattern}{numberFieldsOnce}[true]{\bpNumberFieldsOnce}
\define@key{bitpattern}{numberFieldsTwice}[true]{\bpNumberFieldsTwice}
\define@key{bitpattern}{numberAllBits}[true]{\bpNumberAllBits}
\define@key{bitpattern}{startBit}{\bpStartAtBit{#1}}
\define@key{bitpattern}{bitWidth}{\bpSetBitWidth{#1}}
\define@key{bitpattern}{tickSize}{\bpSetTickHeight{#1}}
% \end{macrocode}
%
% And we can do the same for the package options.
% \begin{macrocode}
\DeclareOption{littleEndian}{\bpLittleEndian}
\DeclareOption{bigEndian}{\bpBigEndian}
\DeclareOption{numberBitsAbove}{\bpNumberBitsAbove}
\DeclareOption{numberBitsBelow}{\bpNumberBitsBelow}
\DeclareOption{noBitNumbers}{\bpNoBitNumbers}
\DeclareOption{numberFieldsOnce}{\bpNumberFieldsOnce}
\DeclareOption{numberFieldsTwice}{\bpNumberFieldsTwice}
\DeclareOption{numberAllBits}{\bpNumberAllBits}
% \end{macrocode}
%
% Set up the default values.
% \begin{macrocode}
\bpLittleEndian
\bpNumberBitsBelow
\bpNumberFieldsOnce
\AtEndOfPackage{\ifbp@NumberBitsBigEndian
\bpStartAtBit{0}\else\bpStartAtBit{7}\fi}
\bpSetBitWidth{1em}
\bpSetTickHeight{2pt}
% \end{macrocode}
%
% And provide the two formatting commands we are using for the
% numbers and the fields.
% \begin{macrocode}
\providecommand\bpFormatField[1]{\strut\emph{#1}}
\providecommand\bpFormatBitNumber[1]{{\tiny\sffamily\strut #1}}
% \end{macrocode}
%
% A few more variables
% \begin{macrocode}
\newcount\bp@CurBit
\newlength{\bp@FieldWidth}
\newlength{\bp@RuleWidth}\setlength{\bp@RuleWidth}{0.4pt}
\newsavebox{\bp@TickBox}
% \end{macrocode}
%
% Now two wrappers around the public formatting hook which call them
% only when the settings are appropriate.
% \begin{macrocode}
\newcommand\bp@FormatTopBit[1]{\ifbp@HasBitNumbers
\ifbp@NumberBitsAbove\bpFormatBitNumber{#1}\fi\fi}
\newcommand\bp@FormatBottomBit[1]{\ifbp@HasBitNumbers
\ifbp@NumberBitsBelow\bpFormatBitNumber{#1}\fi\fi}
% \end{macrocode}
%
% And an helper to get the rule we want for ticks.
% \begin{macrocode}
\newcommand\bp@Tick{\rule{\bp@RuleWidth}{\bp@TickHeight}}
% \end{macrocode}
%
% Small utility to get a vbox without additional vertical spacing
% \begin{macrocode}
\newcommand\bp@vbox[3]
{\parbox[#1]{#2}{\lineskip=0pt\lineskiplimit=0pt\baselineskip=0pt\relax#3}}
% \end{macrocode}
% The function used to put the broken rule when the width is smaller
% than the size.
% \begin{macrocode}
\newcommand\bp@BrokenRuleFill{\dimen0=\bp@RuleWidth\multiply\dimen0 3
\leaders \hrule height \bp@RuleWidth\hfill
\xleaders\hbox to \dimen0{\rule{\bp@RuleWidth}{\bp@RuleWidth}\hfill}\hfill
\leaders \hrule height \bp@RuleWidth\hfill}
% \end{macrocode}
% The function used to put the ticks when the width is smaller than
% the size.
% \begin{macrocode}
\newcommand\bp@BrokenTicks
{\usebox{\bp@TickBox}\usebox{\bp@TickBox}\hfill\usebox{\bp@TickBox}}
% \end{macrocode}
% The function used to put the ticks in the other cases.
% \begin{macrocode}
\newcommand\bp@FillWithTicks
{\leaders\hbox to \bp@BitWidth{\usebox{\bp@TickBox}}\hfill}
% \end{macrocode}
%
% The functions putting the rule and the ticks, choosing between the
% \emph{broken} and non broken version above. They take two
% arguments, the size and the width.
% \begin{macrocode}
\newcommand\bp@RuleFill[2]
{\ifnum #1 = #2
\leaders \hrule height \bp@RuleWidth\hfill
\else
\bp@BrokenRuleFill
\fi}
\newcommand\bp@TicksFill[2]
{\ifnum #1 = #2
\bp@FillWithTicks
\else
\bp@BrokenTicks
\fi}
% \end{macrocode}
% Now a macro to put the bit numbers. It is called with two
% arguments, the width and the alignment. For broken fiels,
% NumberAllBits will be changed to NumberFieldTwice before calling
% this.
% \begin{macrocode}
\newcommand\bp@MakeNumbers[2]{\begingroup\ifbp@NumberAllBits
% \end{macrocode}
% Numbering all the bits is easy, just pay attention to the
% direction.
% \begin{macrocode}
\mbox{\multido{}{#1}{%
\makebox[\bp@BitWidth]{\bpFormatBitNumber{\the\bp@CurBit}}%
\advance\bp@CurBit\ifbp@NumberBitsBigEndian 1\else -1\fi}}%
\else\ifbp@NumberFieldTwice
% \end{macrocode}
% Numbering twice per field has to handle the case where the width is
% 1.
% \begin{macrocode}
\mbox{%
\makebox[\bp@FieldWidth]%
{\makebox[\bp@BitWidth][#2]{\bpFormatBitNumber{\the\bp@CurBit}}%
\ifnum #1 > 1
\advance\bp@CurBit\ifbp@NumberBitsBigEndian #1\else -#1\fi
\advance\bp@CurBit\ifbp@NumberBitsBigEndian -1\else 1\fi
\hfill\makebox[\bp@BitWidth][#2]%
{\bpFormatBitNumber{\the\bp@CurBit}}\fi}}%
\else
% \end{macrocode}
% When numbering only once, one has to pay attention to the alignment
% so that the value is increased beforehand if needed.
% \begin{macrocode}
\ifx#2r
\ifnum #1 > 1
\advance\bp@CurBit\ifbp@NumberBitsBigEndian #1\else -#1\fi
\advance\bp@CurBit\ifbp@NumberBitsBigEndian -1\else 1\fi
\fi\fi
\makebox[\bp@FieldWidth][#2]{\bpFormatBitNumber{\the\bp@CurBit}}%
\fi\fi\endgroup}
% \end{macrocode}
% Call |bp@MakeNumbers| in an appropriate way for the top numbering
% \begin{macrocode}
\newcommand\bp@MakeTopNumbers[1]%
{\ifbp@HasBitNumbers
\ifbp@NumberBitsAbove
\bp@MakeNumbers{#1}{l}
\else
\makebox[\bp@FieldWidth][l]{\hfill}\fi\fi}
% \end{macrocode}
% Call |bp@MakeNumbers| in an appropriate way for the bottom
% numbering
% \begin{macrocode}
\newcommand\bp@MakeBottomNumbers[1]%
{\ifbp@HasBitNumbers
\ifbp@NumberBitsBelow
\bp@MakeNumbers{#1}{r}
\else
\makebox[\bp@FieldWidth][r]{\hfill}\fi\fi}
% \end{macrocode}
% The \cs{bitpattern} is easy, just parse the optional argument in a
% group so that the changes are local and do some more intialization.
% The hard work is delegated to \cs{bp@FieldIfPresent}.
% \begin{macrocode}
\newcommand{\bitpattern}[1][]{%
\begingroup
\setkeys{bitpattern}{#1}%
\savebox{\bp@TickBox}[\bp@BitWidth]{\bp@Tick\hfill}%
\bp@CurBit=\bp@StartBit%
\bp@FieldIfPresent}
% \end{macrocode}
% \cs{bp@FieldIfPresent} checks if we are done and format a field if
% not.
% \begin{macrocode}
\newcommand{\bp@FieldIfPresent}{\@ifnextchar/{\bp@Done}{\bp@Field}}
% \end{macrocode}
% \cs{bp@field} checks if there is an optional argument or call
% \cs{bp@DoField}.
% \begin{macrocode}
\newcommand{\bp@Field}[1]%
{\@ifnextchar[{\bp@SizedField[#1]}{\bp@DoField[#1][1][1]}}
% \end{macrocode}
% \cs{bp@field} checks if there is a second optional argument and
% ensure that \cs{bp@DoField} is called with all the arguments set
% up.
% \begin{macrocode}
\def\bp@SizedField[#1][#2]%
{\@ifnextchar[{\bp@DoField[#1][#2]}{\bp@DoField[#1][#2][#2]}}
% \end{macrocode}
% First argument is field name, second is size, third is width. Do
% some initialization and then format a compact vbox (two are used so
% that the baseline is the one of the field names).
% \begin{macrocode}
\def\bp@DoField[#1][#2][#3]%
{\setlength{\bp@FieldWidth}{\bp@BitWidth * #3}%
\ifnum #2 > #3 \ifbp@NumberAllBits\bpNumberFieldsTwice\fi\fi
\bp@vbox{t}{\bp@FieldWidth}{%
\bp@vbox{b}{\bp@FieldWidth}{%
\bp@MakeTopNumbers{#2}
\makebox[\bp@FieldWidth][s]{\bp@RuleFill{#2}{#3}}
\makebox[\bp@FieldWidth][s]{\bp@TicksFill{#2}{#3}}
\makebox[\bp@FieldWidth][s]%
{\vrule width \bp@RuleWidth\hfil\bpFormatField{#1}\hfil}}
\makebox[\bp@FieldWidth][s]{\bp@TicksFill{#2}{#3}}
\makebox[\bp@FieldWidth][s]{\bp@RuleFill{#2}{#3}}
\bp@MakeBottomNumbers{#2}}%
\advance\bp@CurBit\ifbp@NumberBitsBigEndian #2\else -#2\fi%
\bp@FieldIfPresent}
% \end{macrocode}
% Finalize the pattern by putting a file vertical rule.
% \begin{macrocode}
\def\bp@Done/{\bp@vbox{t}{\bp@RuleWidth}{%
\bp@vbox{b}{\bp@RuleWidth}{%
\makebox[\bp@RuleWidth]{\bp@FormatTopBit{}\hfill}
\makebox[\bp@RuleWidth]{\bp@RuleFill{0}{0}}
\makebox[\bp@RuleWidth]{\bp@Tick\hfill}
\makebox[\bp@RuleWidth]%
{\vrule width \bp@RuleWidth\hfil\bpFormatField{}\hfil}}
\makebox[\bp@RuleWidth]{\bp@Tick\hfill}
\makebox[\bp@RuleWidth]{\bp@RuleFill{0}{0}}
\makebox[\bp@RuleWidth]{\hfill\bp@FormatBottomBit{}}}\endgroup}
% \end{macrocode}
% We can now process the option of the package and we are done.
% \begin{macrocode}
\ProcessOptions
% \end{macrocode}
%
% \Finale
%
\endinput
%%% Local Variables:
%%% fill-column: 69
%%% End:
|