.\" groff implementation of mm(7) package
.\"
.\" See groff_mm(7).
.ig

Copyright 1991-2018 Free Software Foundation, Inc.
          2021-2025 G. Branden Robinson

mm for groff is written by Jörgen Hägg <jh@axis.com>
based on groff ms by James Clark <jjc@jclark.com>
and further developed by Werner Lemberg <wl@gnu.org>
and G. Branden Robinson <g.branden.robinson@gmail.com>.

This file is part of mm, a reimplementation of the Documenter's
Workbench (DWB) troff memorandum macro package for use with GNU troff.

mm is distributed with groff, the GNU roff typesetting system.

groff is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

groff is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

Please submit bug reports using groff's 'BUG-REPORT' file to
http://savannah.gnu.org/bugs/?group=groff.
..
.\" Package identifier naming convention
.\"   name		API, user-visible, global
.\"   @name		global
.\"   module@name	module-specific, public
.\"   module*name	module-specific, private to module
.\"
.\" The latter three may be combined with the following notations.
.\"   env:id		property of *roff environment named "env" (.ev)
.\"   id!index		array element numbered "index"
.
.if !\n(.g \
.  ab groff mm macros require groff extensions; aborting
.
.if \n(.C \
.  ab groff mm macros do not work in compatibility mode; aborting
.
.ds @mm m.tmac\"
.
.if \n[.x]\n[.y]<123 \{\
.  ds @msg \*[@mm]: groff mm macros require groff 1.23 or later,\"
.  as @msg " but found groff \n[.x].\n[.y]; aborting\"
.  ab \*[@msg]
.\}
.
.if d PH .nx
.
.mso devtag.tmac
.
.\" for warnings thrown due to invalid command-line options
.de @usage
.tm \\*[@mm]: warning: \\$*
..
.
.\" for all other kinds of warning
.de @warning
.tm \\*[@mm]:\\n[.F]:\\n[.c]: warning: \\$*
.if r D .if \\n[D] .backtrace
..
.
.\" All errors are fatal.
.de @error
.tm \\*[@mm]:\\n[.F]:\\n[.c]: error: \\$*
.if r D .if \\n[D] .backtrace
.ab
..
.
.de @abort
.tm \\*[@mm]:\\n[.F]:\\n[.c]: internal error: \\$*
.backtrace
.ab
..
.\" ######## initialize package #######
.\"---------------------------------------------
.\"	documented but command-line-only registers
.\"
.\" S and V are handled specially later.
.
.\" XXX: The man page says C isn't supported.  Unfinished?  Check it
.\" against DWB.
.nr @copy_type 0
.if r C .nr @copy_type \n[C]
.
.if r D \{\
.	if \n[D]<0 \{\
.		@usage ignoring out-of-range D register value: \n[D]
.		rr D
.	\}
.\}
.if !r D .nr D 0
.
.if r E \{\
.	if (\n[E]<0):(\n[E]>1) \{\
.		@usage ignoring out-of-range E register value: \n[E]
.		rr E
.	\}
.\}
.if !r E .nr E 1
.ie \n[E] .ds @metadata-font B\"
.el       .ds @metadata-font R\"
.
.if r L \{\
.	if \n[L]<=0 \{\
.		@usage ignoring out-of-range L register value: \n[L]u
.		rr L
.	\}
.\}
.if r L .pl \n[L]u
.
.if r O \{\
.	if \n[O]<0 \{\
.		@usage ignoring out-of-range O register value: \n[O]u
.		rr O
.	\}
.\}
.ie r O .po \n[O]u
.el \{\
.	ie n .po .75i
.	el   .po .963i
.\}
.
.if r W \{\
.	if \n[W]<=0 \{\
.		@usage ignoring out-of-range W register value: \n[W]u
.		rr W
.	\}
.\}
.ie r W .ll \n[W]u
.el     .ll 6i
.\"---------------------------------------------
.\"	Configure type size and vertical spacing.  If given on the
.\"	command line, these have already been converted to basic units.
.if r S \{\
.	if \n[S]<=0 \{\
.		@usage ignoring out-of-range S register value: \n[S]z
.		rr S
.	\}
.\}
.if !r S .nr S 10
.ie \n[S]>=1000 .ps \n[S]z/1000u
.el             .ps \n[S]
.nr *vs-default \n[.ps]*120/100
.
.if r V \{\
.	if \n[V]<=0 \{\
.		@usage ignoring out-of-range V register value: \n[V]u
.		rr V
.	\}
.\}
.if !r V .nr V \n[*vs-default]
.ie \n[V]>=1000 .vs \n[V]p/1000u
.el             .vs \n[V]
.rr *vs-default
.
.nr @ps \n[.ps]
.nr @vs \n[.v]
.if \n[D]>=4 .tm Initialization
.if \n[D]>=5 .tm initialization: @ps=\n[@ps]u, @vs=\n[@vs]u
.if \n[D]>=6 .tm initialization: .l=\n[.l]u, .p=\n[.p]u, .o=\n[.o]u
.nr @pl \n[.p]
.nr @ll \n[.l]
.nr @cur-ll \n[@ll]
.lt \n[@ll]u
.nr @po \n[.o]
.\"---------------------------------------------
.\"	AT&T/DWB public registers and strings
.\"	bullet string
.ds BU \s-2\[bu]\s0
.\"	create table of contents entry for heading of level <= Cl
.nr Cl 2
.\"	suppress page break after TOC lists of figures, tables, ...?
.nr Cp 0
.\"	eject page after floating display?
.nr De 0
.\"	floating display output policy [0..5]
.\"	0 -> at end of section (if N=3 or N=5) or end of document
.\"	1 -> on same page if possible, otherwise end of section/document
.\"	2 -> one float at top of next page/column
.\"	3 -> on same page if possible, otherwise as 2
.\"	4 -> as many floats as fit, starting at top of next page/column
.\"	5 -> on same page if possible, otherwise as 4
.nr Df 5
.\"	vertically space before and after display?
.nr Ds 1
.\"	eject page before headings of level <= Ej
.nr Ej 0
.\"	em dash string
.ds EM \[em]
.\"	align equation labels to the left instead of the right?
.nr Eq 0
.\"	multiple of Lsp to put between items of footnote text
.nr Fs 1
.\"	heading level counters
.nr H1 0 1
.nr H2 0 1
.nr H3 0 1
.nr H4 0 1
.nr H5 0 1
.nr H6 0 1
.nr H7 0 1
.\"	break after headings of level <= Hb
.nr Hb 2
.\"	center headings of level <= Hc
.nr Hc 0
.\"	heading font, per level
.ds HF 2 2 2 2 2 2 2
.\"	indentation policy of text after headings
.\"	0 -> no indentation
.\"	1 -> first-line indentation, like ".P 1"
.\"	2 -> indent to line up with text part of preceding heading
.nr Hi 1
.\"	header point (type) size, per level
.ds HP 0 0 0 0 0 0 0
.\"	put vertical space of \n[Hss] after headings of level <= Hs
.nr Hs 2
.\"	heading numbering type
.\"	0 -> multiple (1.1.1 ...)
.\"	1 -> single
.nr Ht 0
.\"	unnumbered headings format like numbered headings of this level
.nr Hu 2
.\"	automatic hyphenation enabled?
.nr Hy 0
.\"	captions of lists potentially appearing in table of contents
.ds Lf LIST OF FIGURES
.nr Lf 1
.ds Lt LIST OF TABLES
.nr Lt 1
.ds Lx LIST OF EXHIBITS
.nr Lx 1
.ds Le LIST OF EQUATIONS
.nr Le 1 \" This default differs from DWB 3.3 mm.
.\"	list indentation in ens
.nr Li 5
.\"	put vertical space before list items of nesting level <= Ls
.nr Ls \n[.R]
.\"	page numbering style [0..5]
.\"	0 -> p. 1: header;                pp. 2 on: header
.\"	1 -> p. 1: move header to footer; pp. 2 on: header
.\"	2 -> p. 1: no header;             pp. 2 on: header
.\"	3 -> p. 1: section-page;          pp. 2 on: as p. 1
.\"	4 -> p. 1: no header;             pp. 2 on: none (unless .PH)
.\"	5 -> p. 1: section-figure;        pp. 2 on: as p. 1
.if !r N .nr N 0
.\"	number paragraphs under first-level headings?
.nr Np 0
.\"	format of figure,table,exhibit,equation titles
.\"	0= ". ", 1=" - "
.nr Of 0
.\"	table of contents page numbering style
.nr Oc 0
.\"	page number, normally same as \n[%]
.nr P 0
.\"	paragraph indentation in ens
.nr Pi 5
.\"	multiple of Lsp to put between paragraphs
.nr Ps 1
.\"	paragraph indentation policy (for .P)
.\"	0 -> no indentation
.\"	1 -> indented by \n[Pi]
.\"	2 -> indented by \n[Pi] except after .H, .HU, .DE, or .LE
.nr Pt 0
.\"	reference list caption
.ds Rp REFERENCES\"
.\"	display indentation in ens
.nr Si 5
.\"---------------------------------------------
.\"	AT&T/DWB strings that interpolate letter-like symbols
.\" TODO: Query only the selected font (\n[.fn]) for the applicable
.\" glyphs; falling back to a special font might result in serifed
.\" trademark signs with a sans serif text font, for example.  We need a
.\" new GNU troff feature for that.  See Savannah #64004.
.\"	registered (trade mark) string
.ie c \[u00AE] .ds Rg \[u00AE]\"
.el \{\
.	\" This overstricken glyph looks okay with Times roman.
.	ie t .ds Rg \Z'\s-4\h@.35m@\v@-.2m@R\s0'\s+4\[ci]\s0\"
.	el   .ds Rg \u(R)\d\"
.\}
.\"	service mark string
.ie c \[u2120] .ds Sm \[u2120]\"
.el \{\
.	ie t .ds Sm \v'-.4m'\s-3SM\s0\v'.4m'\"
.	el   .ds Sm \u(SM)\d\"
.\}
.\"	trade mark string
.ie c \[tm] .ds Tm \[tm]\"
.el \{\
.	ie t .ds Tm \v'-.4m'\s-3TM\s0\v'.4m'\"
.	el   .ds Tm \u(TM)\d\"
.\}
.
.nr @in-verbatim-region 0
.\"---------------------------------------------
.\"	public groff mm extension registers and strings
.
.\" Indicate groff mm macro package; documents may test this.
.nr .mgm 1
.\" Abstract caption
.ds Abstract ABSTRACT\"
.\" Appendix caption
.ds App APPENDIX
.\" format appendix caption?
.nr Aph 1
.\" appendix text possibly set by APP or APPSK
.ds Apptext \" empty
.\" spacing before and after static displays (if undefined, Lsp is used)
.\" .nr Dsp 1v
.\" more heading level counters
.as HF " 2 2 2 2 2 2 2
.as HP " 0 0 0 0 0 0 0
.nr H8 0 1
.nr H9 0 1
.nr H10 0 1
.nr H11 0 1
.nr H12 0 1
.nr H13 0 1
.nr H14 0 1
.\" add a dot after level one heading number?
.nr H1dot 1
.\" put vertical space of \n[Hps2] before headings of level <= Hps
.nr Hps 1
.\" amount of vertical space before headings when level > Hps
.ie t .nr Hps1 0.5v
.el   .nr Hps1 1v
.\" amount of vertical space before headings when level <= Hps
.ie t .nr Hps2 1v
.el   .nr Hps2 2v
.\" multiple of Lsp to put after a heading
.nr Hss 1
.\" H1txt is updated by .H and .HU, containing the heading text.
.\" .TC and lix@print-ds also update it.
.ds H1txt \" empty
.\" caption for the index
.ds Index INDEX
.\" use ISO 8601 date format?
.nr Isodate 0
.aln Iso Isodate \" for groff <= 1.23 compatibility
.\" flag for mkindex (XXX: undocumented: do we need this?)
.if !r Idxf .nr Idxf 0
.\" captions for displays
.ds Capec Equation
.ds Capex Exhibit
.ds Capfg Figure
.ds Captb Table
.\" caption for the table of contents
.ds Captc CONTENTS
.\" aliases for groff <= 1.23 compatibility
.als Licon Captc
.als Liec Capec
.als Liex Capex
.als Lifg Capfg
.als Litb Captb
.\" Lsp controls the height of an empty line. Normally 0.5v
.\" Normally used for nroff compatibility.
.ie t .nr Lsp 0.5v
.el   .nr Lsp 1v
.
.\" Note: See comment under `cov*set-date` macro definition.
.ds MO1 January
.ds MO2 February
.ds MO3 March
.ds MO4 April
.ds MO5 May
.ds MO6 June
.ds MO7 July
.ds MO8 August
.ds MO9 September
.ds MO10 October
.ds MO11 November
.ds MO12 December
.
.\" use body text size and vertical spacing for titles?
.nr Pgps 1
.
.\" Text printed below the footer. Controlled by @copy_type (C).
.\" (XXX: undocumented)
.ds Pg_type!0
.ds Pg_type!1 OFFICIAL FILE COPY
.ds Pg_type!2 DATE FILE COPY
.ds Pg_type!3 D\ R\ A\ F\ T
.ds Pg_type!4 D\ R\ A\ F\ T
.
.\" for GETR
.ds Qrf See chapter \E*[Qrfh], page \E*[Qrfp].
.\" output reference marks to standard error?
.if !r Ref .nr Ref 0
.\" reference mark style
.\" 0 = auto (nroff/troff); 1 = bracket; 2 = superscript; 3 = both
.nr Rfstyle 0
.\" reference list page ejection policy
.nr Rpej 0
.aln Rpe Rpej \" for groff <= 1.23 compatibility
.\" reference list format (arguments to `LB`)
.ds Rpfmt \\n[Li] 0 1 0 \& 0\"
.\" use section-page page numbering?
.nr Sectp 0
.if (\n[N]=3):(\n[N]=5) \{\
.	nr Sectp 1
.	nr Ej 1
.\}
.\" use section-figure page numbering?
.ie \n[N]=5 .nr Sectf 1
.el         .nr Sectf 0
.\" state of TOC formatting
.\" This is empty outside the table of contents; inside it is set to co,
.\" fg, tb, ec, ex, or ap.
.ds Tcstatus \" empty
.\" alias for groff <= 1.23 compatibility
.als Tcst Tcstatus
.\" argument(s) for VERBON to give to `nm` request
.ds Verbnm 1\"
.\" indentation of verbatim regions (VERBON)
.nr Verbin 5n
.
.\" Letter section
.\" Formal closing (.FC)
.ds Letfc Yours very truly,
.
.\" Approval line
.ds Letapp APPROVED:
.\" Approval date-string
.ds Letdate Date
.
.ds LetCN CONFIDENTIAL\"		Confidential default
.ds LetSA To Whom It May Concern:\"	Salutation default
.ds LetAT ATTENTION:\"			Attention string
.ds LetSJ SUBJECT:\"			Subject string
.ds LetRN In reference to:\"		Reference string
.
.\" Copy to (.NS)
.ds Letnsdef 0
.ds Letns!copy Copy \" space!
.ds Letns!to " to
.ds Letns!0 Copy to
.ds Letns!1 Copy (with att.\&) to
.ds Letns!2 Copy (without att.\&) to
.ds Letns!3 Att.
.ds Letns!4 Atts.
.ds Letns!5 Enc.
.ds Letns!6 Encs.
.ds Letns!7 Under separate cover
.ds Letns!8 Letter to
.ds Letns!9 Memorandum to
.ds Letns!10 Copy (with atts.\&) to
.ds Letns!11 Copy (without atts.\&) to
.ds Letns!12 Abstract Only to
.ds Letns!13 Complete Memorandum to
.ds Letns!14 CC:
.\" maximum number of productive input lines read into `WA` information
.nr Letwam 14
.
.\"---------------------------------------------
.\" Localize package.
.ie d @country .msoquiet mm/\*[@country]_locale
.el            .msoquiet mm/locale
.\"---------------------------------------------
.de @enable-hyphenation
.ie r .hydefault .hy \" Use groff 1.24 feature.
.el              .hy \\n[\\*[locale]*hyphenation-mode-trap]
..
.\"	reset all the things (except `ce`, `rj`, `ul`, and `cu`)
.de @reset
.ie \\n[misc@adjust] .ad
.el                  .na
.ie \\n[Hy] .@enable-hyphenation
.el         .nh
'in 0
'ti 0
.ps \\n[@ps]u
.vs \\n[@vs]u
.ref*set-mark-style \" in case the document has changed it
..
.de misc@toupper
.tr aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ
.br
\\$1
.tr aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz
.br
..
.\" ####### module debug #################################
.\"
.\" A sketch of debugging level meanings:
.\"   0: no non-diagnostic output
.\"   1: gross formatting progress: report each page start
.\"   2: report output of certain structural elements*
.\"   3: report output of headers/footers
.\"   4: report init, EOI macro, population and emission of diversions
.\"   5: trace API macro calls, sprung traps, and init/shutdown
.\"   6: dump internal computations
.\"
.\" * headings, footnotes, captioned items, references
.de debug@dump-args
.if \\n[D]>=5 \{\
.	tmc \\$0:
.	ie \\n[.$] .tm1 " \\$@
.	el         .tm1 " no arguments
.\}
..
.
.de debug@box
.if \\n[D]>=4 \{\
.  ie \\n[.$] .tm Starting box diversion "\\$*"
.  el         .tm Closing box diversion "\\n[.z]"
.\}
.box \\$*
..
.
.de debug@di
.if \\n[D]>=4 \{\
.  ie \\n[.$] .tm Starting diversion "\\$*"
.  el         .tm Closing diversion "\\n[.z]"
.\}
.di \\$*
..
.
.de debug@da
.if \\n[D]>=4 \{\
.  ie \\n[.$] .tm Appending to diversion "\\$*"
.  el         .tm Closing diversion "\\n[.z]"
.\}
.da \\$*
..
.
.de debug@emit
.if \\n[D]>=4 .tm Emitting diversion "\\$*"
.\\$*
..
.
.\" We assume that people calling these macros understand that register
.\" values are stored in basic units.
.de debug@little-dump
.tmc \\$1:\\n[.F]:\\n[c.] ll=\\n[.l] vs=\\n[.v] ps=\\n[.s]z,\\n[.ps]s
.tm1 " in=\\n[.i] fi=\\n[.u] .d=\\n[.d] nl=\\n[nl] pg=\\n[%]
..
.de debug@big-dump
.nr debug*n 1n
.nr debug*m 1m
.tmc \\$1:\\n[.F]:\\n[c.] ll=\\n[.l] vs=\\n[.v] ps=\\n[.s]z in=\\n[.i]
.tm1 " ad=\\n[.j] fi=\\n[.u] pl=\\n[.p] page=\\n[%] .o=\\n[.o]
.tmc _______ .d=\\n[.d] .f=\\n[.f] .h=\\n[.h] .k=\\n[.k] .n=\\n[.n]
.tmc " .p=\\n[.p] .t=\\n[.t] .z=\\n[.z] nl=\\n[nl] dn=\\n[dn]
.tm1 " n=\\n[debug*n], m=\\n[debug*m]
.rr debug*n debug*m
..
.\" ####### module par #################################
.nr par*indentation-eligible 1		\" indent following P if Pt=2
.nr par@suppress-indentation 0
.nr hd*last-pos -1
.nr hd*last-hsize -1
.nr par*nP-counter 0 1
.af par*nP-counter 00
.nr par*Np-counter 0 1
.af par*Np-counter 00
.\"------------
.\" paragraph
.de P
\\*[debug@dump-args]\\
.if \\n[.$] \{\
.	ie !\B'\\$1' \{\
.		@warning \\$0: ignoring non-numeric argument: '\\$1'
.		shift
.	\}
.	el .if \\$1>1 \
.		@warning \\$0: ignoring unsupported paragraph type \
'\\$1'
.\}
.\"	skip P if previous heading
.if \\n[D]>=6 \{\
.	tm \\$0: paragraph nl=\\n[nl]u, hd*last-pos=\\n[hd*last-pos]u
.	tm \\$0: paragraph .k=\\n[.k]u, \
hd*last-hsize=\\n[hd*last-hsize]u
.\}
.nr par*indentation-eligible 1-\\n[par@suppress-indentation]
.par@doit \\$*
.if \\n[Np] \\n[H1].\\n+[par*Np-counter]\ \ \c
..
.\"------------
.de nP
\\*[debug@dump-args]\\
.if \\n[D]>=6 \{\
.	tm \\$0: paragraph nl=\\n[nl]u, hd*last-pos=\\n[hd*last-pos]u
.	tm \\$0: paragraph .k=\\n[.k]u, \
hd*last-hsize=\\n[hd*last-hsize]u
.\}
.\" `nP` handles indentation differently from `P`.
.nr par*indentation-eligible 0
.par@doit
\\n[H2].\\n+[par*nP-counter]\ \ \c
.\" Indent the paragraph's second line, too.
'ti \w'\\n[H2].\\n[par*nP-counter]'u+2n
..
.\"------------
.de par@doit
.SP (u;\\n[Ps]*\\n[Lsp])
.nr par*do-indent 0
.ie \\n[.$] \{\
.	if \\$1=1 .nr par*do-indent 1
.\}
.el \{\
.	if \\n[Pt]=1 .nr par*do-indent 1
.	if (\\n[Pt]=2)&\\n[par*indentation-eligible] \
.		nr par*do-indent 1
.\}
.if \\n[par*do-indent] .ti +\\n[Pi]n
.rr par*do-indent
.nr par@suppress-indentation 0
.ref*set-mark-style \" in case the document has changed it
..
.\" ####### module line #######################################
.de SP
\\*[debug@dump-args]\\
.br
.if !r line*lp\\n[.z] .nr line*lp\\n[.z] 0
.if !r line*ac\\n[.z] .nr line*ac\\n[.z] 0
.ie \\n[.$] \{\
.	if !\B'\\$1' .@error \\$0: argument is not numeric: '\\$1'
.	if \\$1<0 .@error \\$0: negative motion '\\$1' not supported
.	nr line*temp (v;\\$1)
.\}
.el .nr line*temp 1v
.\"
.ie \\n[line*lp\\n[.z]]=\\n[.d] \{\
.	\" go here if no output since the last .SP
.	nr line*output \\n[line*temp]-\\n[line*ac\\n[.z]]
.	if \\n[line*output]<0 .nr line*output 0
.	nr line*ac\\n[.z] +\\n[line*output]
.\}
.el \{\
.	nr line*ac\\n[.z] \\n[line*temp]
.	nr line*output \\n[line*temp]
.	\" no extra space in the beginning of a page
.	if (\\n[.d]<0):(\\n[pg*head-mark]=\\n[.d]) .nr line*output 0
.\}
.if \\n[line*output] .sp \\n[line*output]u
.nr line*lp\\n[.z] \\n[.d]
..
.\" ######## module misc ###############
.\" XXX: This register value is meaningless.
.\"   .ad b
.\"   .nr misc@adjust \n[.j]
.\" might be better...
.nr misc@adjust 14
.de SA
\\*[debug@dump-args]\\
.if \\n[.$] \{\
.	if !\B'\\$1' .@error \\$0: argument is not numeric: '\\$1'
.	if (\\$1<0):(\\$1>1) .@error \\$0: invalid argument: '\\$1'
.\" XXX: ...then...
.\"   .ad l
.\"   .nr misc@adjust \\n[.j]
.	nr misc@adjust 0\\$1
.\}
.\" XXX: ...and finally an unconditional.
.\"   .ad \\n[.j]
.ie \\n[misc@adjust] .ad
.el                  .na
..
.\"-------------
.\" switch environment, keep all important settings.
.de misc@ev-keep
.nr misc*ll \\n[.l]
.ds misc*fam \\n[.fam]
.ev \\$1
.ll \\n[misc*ll]u
.lt \\n[misc*ll]u
.fam \\*[misc*fam]
..
.\"-------------
.\" .misc@push stackname value
.de misc@push
.ie d misc*st-\\$1 .ds misc*st-\\$1 \\$2 \\*[misc*st-\\$1]
.el .ds misc*st-\\$1 \\$2
..
.\"-------------
.\" .misc@pop stackname
.\" value returned in the string misc*pop
.de misc@pop
.misc@pop-set misc*st-\\$1 \\*[misc*st-\\$1]
..
.\"-------------
.de misc@pop-set
.ds misc*st-name \\$1
.shift
.if \\n[.$]<1 .@abort stack '\\*[misc*st-name]' empty
.ds misc*pop \\$1
.shift
.ds \\*[misc*st-name] \\$*
..
.\"-------------
.\" .misc@pop-nr stackname varname
.de misc@pop-nr
.misc@pop \\$1
.nr \\$2 0\\*[misc*pop]
..
.\"-------------
.\" .misc@pop-ds stackname varname
.de misc@pop-ds
.misc@pop \\$1
.ds \\$2 \\*[misc*pop]
..
.\"-----------
.\" reset tabs
.de TAB
\\*[debug@dump-args]\\
.ta T 5n
..
.\"-------------
.\" .PGFORM linelength [ pagelength [ pageoffset [1]]]
.de PGFORM
\\*[debug@dump-args]\\
.\" Break here to avoid problems with new linesetting of the previous line.
.\" Hope this doesn't break anything else :-)
.\" Don't break if arg_4 is a '1'.
.if ''\\$4' .br
.if \\n[D]>=6 .tm \\$0: IN l:\\n[.l] p:\\n[.p] o:\\n[.o]
.ie !''\\$1' \{\
.	ll \\$1
.	nr @ll \\n[.l]
.	nr @cur-ll \\n[@ll]
.	lt \\n[@ll]u
.\}
.el \{\
.	ll \\n[@ll]u
.	lt \\n[@ll]u
.\}
.\"
.ie !''\\$2' \{\
.	pl \\$2
.	nr @pl \\n[.p]
.\}
.el .pl \\n[@pl]u
.\"
.ie !''\\$3' \{\
.	po \\$3
.	nr @po \\n[.o]
.\}
.el .po \\n[@po]u
.if \\n[D]>=6 .tm \\$0: OUT l:\\n[.l] p:\\n[.p] o:\\n[.o]
.if \\n[D]>=6 .tm \\$0: ll=\\n[@ll], pl=\\n[@pl], po=\\n[@po]
'in 0
.pg@move-trap
.if \\n[D]>=6 \{\
.	tm Traps:
.	pwh
.\}
..
.\"-------------
.\" .MOVE y [[x] linelength]
.\" move to line y, indent to x
.de MOVE
\\*[debug@dump-args]\\
.if !\\n[.$] \{\
.	@warning \\$0: ignoring; no arguments specified
.	return
.\}
.if \\n[nl]<0 \c
.\" move to Y-pos
.sp |(v;\\$1)
.\" calc linelength
.ie \\n[.$]>2 .nr pg*i (n;\\$3)
.el \{\
.	ie \\n[.$]>1 .nr pg*i (n;\\n[@ll]u-\\$2)
.	el .nr pg*i \\n[@ll]u
.\}
.\" move to X-pos, if any
.if !''\\$2' .po \\$2
.\" set linelength
.ll \\n[pg*i]u
..
.\"-------------
.de SM
\\*[debug@dump-args]\\
.if !\\n[.$] \{\
.	@warning \\$0: ignoring; no arguments specified
.	return
.\}
.if \\n[.$]=1 \s-1\\$1\s0
.if \\n[.$]=2 \s-1\\$1\s0\\$2
.if \\n[.$]=3 \\$1\s-1\\$2\s0\\$3
..
.\"-------------
.nr misc*S-ps \n[@ps]
.nr misc*S-vs \n[@vs]
.nr misc*S-ps1 \n[@ps]
.nr misc*S-vs1 \n[@vs]
.ds misc*a
.ds misc*b
.
.de S
\\*[debug@dump-args]\\
.ie !\\n[.$] \{\
.	ds misc*a P
.	ds misc*b P
.\}
.el \{\
.	ie \\n[.$]=1 .ds misc*b D
.	el \{\
.		ie \w@\\$2@=0 .ds misc*b C
.		el .ds misc*b \\$2
.	\}
.	ie \w@\\$1@=0 .ds misc*a C
.	el .ds misc*a \\$1
.\}
.\"
.\" set point size
.if !'\\*[misc*a]'C' \{\
.	ie '\\*[misc*a]'P' .ps \\n[misc*S-ps]u
.	el \{\
.		ie '\\*[misc*a]'D' .ps \\n[S]
.		el                 .ps \\*[misc*a]
.	\}
.	if \\n[D]>=6 .tm \\$0: .ps=\\n[.ps]u
.\}
.\"
.\" set vertical spacing
.if !'\\*[misc*b]'C' \{\
.	ie '\\*[misc*b]'P' .vs \\n[misc*S-vs]u
.	el \{\
.		ie '\\*[misc*b]'D' .vs \\n[.ps]s+2p
.		el                 .vs \\*[misc*b]
.	\}
.	if \\n[D]>=6 .tm \\$0: .v=\\n[.v]u
.\}
.nr @ps  \\n[.ps]
.nr @psu \\n[.ps]s
.nr @vs  \\n[.v]
.nr @vsp \\n[.v]u/1p
.nr @res 1i
.\"
.if \\n[D]>=6 \{\
.	tmc \\$0: misc*a=\\*[misc*a], misc*b=\\*[misc*b]
.	tmc " => ps:\\n[.s]z (\\n[@psu]u), vs:\\n[@vsp]p (\\n[@vs]u),
.	tm1 " (res:\\n[@res])
.\}
.nr misc*S-ps  \\n[misc*S-ps1]
.nr misc*S-vs  \\n[misc*S-vs1]
.nr misc*S-ps1 \\n[@ps]
.nr misc*S-vs1 \\n[@vs]
.pg@move-trap
..
.\"------------
.de HC
\\*[debug@dump-args]\\
.ev 0
.hc \\$1
.ev
.ev 1
.hc \\$1
.ev
.ev 2
.hc \\$1
.ev
..
.\"------------
.de RD
\\*[debug@dump-args]\\
.debug@di misc*rd \" never emitted
'fl
.\" TODO: get rid of the `\t` to enable more user control
.rd \\$1\t
.br
.debug@di
.if !''\\$3' \{\
.	debug@di misc*rd2 \" never emitted
.	ds \\$3 "\\*[misc*rd]
.	br
.	debug@di
.\}
.if !''\\$2' .rn misc*rd \\$2
.rm misc*rd misc*rd2
..
.\"------------
.\" VERBON [format [type-size [font]]]
.\"	format
.\"	bit	function
.\"	0	escape character disablement
.\"	1	add an empty line before verbatim text
.\"	2	add an empty line after verbatim text
.\"	3	number output lines using Verbnm string for .nm args
.\"	4	indent text by amount in register Verbin
.de VERBON
\\*[debug@dump-args]\\
.nr misc*verb 0
.if !'\\$1'' \{\
.	ie \B'\\$2' .nr misc*verb \\$1
.	el          .@error \\$0: format argument is not numeric; got \
'\\$1'
.\}
.br
.if (\\n[misc*verb]%4)/2 .SP \\n[Lsp]u
.misc@ev-keep misc*verb-ev
.nf
.if (\\n[misc*verb]%16)/8 .nm \\*[Verbnm]
.ie !'\\$3'' .if F \\$3 .ft \\$3
.el          .if F CR   .ft CR
.ie !'\\$2'' \{\
.	ss \\$2
.	ps \\$2
.	vs \\$2
.\}
.el .ss 12
.ta T 8u*\w@n@u
.if (\\n[misc*verb]%32)/16 .in +\\n[Verbin]u
.if \\n[misc*verb]%2 \{\
.	eo
.	nr @in-verbatim-region 1
.\}
..
.de VERBOFF
\\*[debug@dump-args]\\
.ec
.br
.if (\\n[misc*verb]%8)/4 .SP \\n[Lsp]u
.if (\\n[misc*verb]%16)/8 .nm
.if (\\n[misc*verb]%32)/16 .in
.ev
.nr @in-verbatim-region 0
..
.\" Wrapper to cancel the side effect of .tag + .br generating
.\" unwanted vertical space.
.de misc@tag
.\" This macro is currently used solely to give information to the
.\" HTML postprocessor.  If for PostScript or PDF output macro .H
.\" had been followed by .DS both .H post-space and .DS pre-space
.\" had been output because of this macro.  So it is now enabled
.\" only when postprocessor tags are required.
.if '\*[.T]'html' \{\
.\" retain temporary indentation and horizontal position
.if !(\\n[.in]-\\n[.i]=0) .nr misc*ti \\n[.in]
.nr misc*.k \\n[.k]
.vpt 0
.DEVTAG-\\$1 \\$2
.br
.if r misc*ti \{\
.	ti \\n[misc*ti]u
.	rr misc*ti
.	sp -1
.\}
.sp -1
\h'\\n[misc*.k]u'\c
.rr misc*.k
.vpt 1
.\}
..
.\" ######## module pict #################
.nr pict*width 0
.nr pict*height 0
.nr pict*mode 0
.nr pict*ind 0
.nr pict*id 0 1
.\" I assume that the number variable pict*id is the same
.\" between two runs.
.de PIC
\\*[debug@dump-args]\\
.br
.nr pict*ind 0
.nr pict*box 0
.while \\n[.$]>0 \{\
.	if '-B'\\$1' \{\
.		nr pict*box 1
.		shift
.		continue
.	\}
.	if '-L'\\$1' \{\
.		nr pict*mode 0
.		shift
.		continue
.	\}
.	if '-R'\\$1' \{\
.		nr pict*mode 1
.		shift
.		continue
.	\}
.	if '-I'\\$1' \{\
.		nr pict*ind (n;\\$2)
.		nr pict*mode 2
.		shift 2
.		continue
.	\}
.	if '-C'\\$1' \{\
.		nr pict*mode 3
.		shift
.		continue
.	\}
.	ds pict*f \\$1
.	nr pict*id +1
.	shift
.	if \\n[.$]>0 \{\
.		if !\B'\\$1' .@error \\$0: width parameter is not \
numeric; got '\\$1'
.		nr pict*width (i;\\$1)
.		shift
.	\}
.	if \\n[.$]>0 \{\
.		if !\B'\\$1' .@error \\$0: height parameter is not \
numeric; got '\\$1'
.		nr pict*height (i;\\$1)
.		shift
.	\}
.\}
.\" let mmroff know the filename and id
.if \\n[Ref]>0 \{\
.	tm .\\\\" PIC id \\n[pict*id]
.	tm .\\\\" PIC file \\*[pict*f]
.\}
.\" these are defined by mmroff in the second pass
.if d pict*file!\\n[pict*id] \{\
.	ds pict*f \\*[pict*file!\\n[pict*id]]
.	nr pict*llx \\n[pict*llx!\\n[pict*id]]
.	nr pict*lly \\n[pict*lly!\\n[pict*id]]
.	nr pict*urx \\n[pict*urx!\\n[pict*id]]
.	nr pict*ury \\n[pict*ury!\\n[pict*id]]
.	\"
.	nr pict*w (p;\\n[pict*urx]-\\n[pict*llx])
.	if \\n[pict*w]<0 .nr pict*w 0-\\n[pict*w]
.	nr pict*h (p;\\n[pict*ury]-\\n[pict*lly])
.	if \\n[pict*h]<0 .nr pict*h 0-\\n[pict*h]
.	if \\n[pict*width]>0 \{\
.		nr pict*rs (u;1000*\\n[pict*width]/\\n[pict*w])
.		nr pict*w (u;\\n[pict*w]*\\n[pict*rs]/1000)
.		nr pict*h (u;\\n[pict*h]*\\n[pict*rs]/1000)
.	\}
.	if \\n[pict*height]>0 \{\
.		nr pict*rs (u;1000*\\n[pict*height]/\\n[pict*h])
.		nr pict*h (u;\\n[pict*h]*\\n[pict*rs]/1000)
.	\}
.	if '0'\\n[pict*mode]' \{\
.		nr pict*in \\n[.i]u
.	\}
.	if '1'\\n[pict*mode]' \{\
.		nr pict*in (u;\\n[.l]-\\n[.i]-\\n[pict*w])
.	\}
.	if '2'\\n[pict*mode]' \{\
.		nr pict*in \\n[pict*ind]u
.	\}
.	if '3'\\n[pict*mode]' \{\
.		nr pict*in (u;(\\n[.l]-\\n[.i]-\\n[pict*w])/2)
.	\}
.	ds pict*h "
.	if \\n[pict*h]>0 .ds pict*h \\n[pict*h]
.	\"
.	ne \\n[pict*h]u-1v
.	\"
.	\" these lines are copied and modified from pspic.tmac.
.	\" Originally written by James Clark
.	br
.	ie \\n[pict*box]>0 \{\
\v'-1v'\h'\\n[pict*in]u'\
\Z'\D'p 0 \\n[pict*h]u \\n[pict*w]u 0 0 -\\n[pict*h]u''\
\v'\\n[pict*h]u'\X'ps: import \\*[pict*f] \
\\n[pict*llx] \\n[pict*lly] \
\\n[pict*urx] \\n[pict*ury] \
\\n[pict*w] \\n[pict*h]'
.\}
.	el \{\
\v'-1v'\h'\\n[pict*in]u'\
\X'ps: invis'\
\Z'\D'p 0 \\n[pict*h]u \\n[pict*w]u 0 0 -\\n[pict*h]u''\
\X'ps: endinvis'\
\v'\\n[pict*h]u'\X'ps: import \\*[pict*f] \
\\n[pict*llx] \\n[pict*lly] \
\\n[pict*urx] \\n[pict*ury] \
\\n[pict*w] \\n[pict*h]'
.	\}
.	br
.	sp \\n[pict*h]u-1v
.\}
..
.\" external picture
.\" -L	left align
.de EPIC
\\*[debug@dump-args]\\
.nr pict*adj 0		\" centered
.if '\\$1'-L' \{\
.	shift
.	nr pict*adj 1
.\}
.if \\n[.$]<2 \{\
.	@warning \\$0: ignoring; expected width and height arguments
.	return
.\}
.\" Permit a document to start with EPIC.
.if \\n[nl]<0 \&
.ie \B'\\$1' .nr pict*w (n;\\$1)
.el          .@error \\$0: width argument is not numeric: '\\$1'
.ie \B'\\$2' .nr pict*h (v;\\$2)
.el          .@error \\$0: height argument is not numeric: '\\$2'
.\" XXX: This is kind of lame.  It's also not localized.
.ds pict*name External picture\"
.if !''\\$3' .ds pict*name " \\$3\"
.ne \\n[pict*h]u
.sp \\n[pict*h]u-1v
.nr pict*ind 0
.if !\\n[pict*adj] .nr pict*ind (u;(\\n[.l]-\\n[.i]-\\n[pict*w])/2)
.mk
.in +\\n[pict*ind]u
\D'l \\n[pict*w]u 0'\
\D'l 0 -\\n[pict*h]u'\
\D'l -\\n[pict*w]u 0'\
\D'l 0 \\n[pict*h]u'\
\v'-(u;\\n[pict*h]/2)'\
\h'(u;(\\n[pict*w]-\w'\\*[pict*name]'/2))'\\*[pict*name]
.in
.rt
.sp 1v
..
.\" ######## module acc #################
.\"-----------
.\" accents. These are copied from mgs, written by James Clark.
.de acc@over-def
.ds \\$1 \Z'\v'(u;\w'x'*0+\En[rst]-\En[.cht])'\
\h'(u;-\En[skw]+(-\En[.w]-\w'\\$2'/2)+\En[.csk])'\\$2'
..
.de acc@under-def
.ds \\$1 \Z'\v'\En[.cdp]u'\h'(u;-\En[.w]-\w'\\$2'/2)'\\$2'
..
.acc@over-def ` \`
.acc@over-def ' \'
.acc@over-def ^ ^
.acc@over-def ~ ~
.acc@over-def : \[ad]
.acc@over-def ; \[ad]
.acc@under-def , \[ac]
.\" ######## module uni #################
.\" unimplemented macros
.de @disable
.ds @end \" empty
.while \\n[.$] \{\
.	rm \\$1 \" in case it's aliased
.	de \\$1 @end
.		@warning \\$1: ignoring; unavailable after \\*[@cover]
.	@end
.	shift
.\}
..
.rm @end
.
.de CS
.@warning \\$0: not implemented except with ".MT 4"
..
.de OK
.@warning \\$0: not implemented
..
.de PM
.@warning \\$0: not implemented
..
.\" ######## module hd #################
.\" support for usermacro
.nr hd*h1-page 1	\" last page-number for level 1 header.
.nr hd*htype 0
.ds hd*sect-pg
.ds hd*mark
.ds hd*suf-space
.nr hd*need 0
.aln ;0 hd*htype
.als }0 hd*mark
.als }2 hd*suf-space
.aln ;3 hd*need
.\"-------------
.\" .hd@split variable index name val1 val2 ...
.de hd@split
.\" TODO: Verify that this isn't reachable due to ordinary user error;
.\" if it is, make it an @error.
.if \\$2>(\\n[.$]-3) .@abort \\$3 must have at least \\$2 values \
(\\*[\\$3])
.nr hd*sp-tmp \\$2+3
.ds \\$1 \\$[\\n[hd*sp-tmp]]
..
.de HU
\\*[debug@dump-args]\\
.if \\n[.$]=0 .@error \\$0: expected 1 or 2 arguments, got \\n[.$]
.H 0 \\$@
..
.\"-------------
.de hd*trap
.nr par@suppress-indentation 0
..
.\"-------------
.de H
.if \\n[.$]=0 .@error \\$0: expected 1 to 3 arguments, got \\n[.$]
.if !\B'\\$1' .@error \\$0: level argument is not numeric: '\\$1'
\\*[debug@dump-args]\\
.if !r hd*cur-bline .nr hd*cur-bline \\n[nl]
.br
.df@print-float 2\"	$$$ could be wrong...
.\" terminate all lists
.LC
.@reset
.nr hd*level 0\\$1
.nr hd*arg1 0\\$1
.if !\\n[hd*level] .nr hd*level \\n[Hu]
.\"
.\"	clear lower counters
.nr hd*i 1 1
.while \\n+[hd*i]<15 .if \\n[hd*level]<\\n[hd*i] .nr H\\n[hd*i] 0 1
.\"
.\" save last text for use in TP
.if \\n[hd*level]=1 .ds H1txt \\$2\\$3
.\"
.\" This is a little fix to be able to get correct H1 heading number
.\" in page headers. Special attention was needed when other formats are used.
.ie !''\\g[H1]' \{\
.	ds hd*format \\g[H1]
.	af H1 0
.	nr H1h \\n[H1] 1
.	af H1 \\*[hd*format]
.\}
.el .nr H1h \\n[H1] 1
.if \\n[hd*level]=1 .nr H1h +1
.\"
.\" Break page before headings of level <= Ej.
.if (\\n[hd*level]<=\\n[Ej])&(\\n[nl]>\\n[hd*cur-bline]) .pg@next-page
.\"
.\" increment current counter
.nr H\\n[hd*level] +1
.\"
.\" update pagenumber if section-page is used
.if (\\n[hd*level]=1)&(\\n[Sectp]>0) .hd@set-page 1
.\"
.\" hd*mark is the text written to the left of the header.
.ds hd*mark \\n[H1].
.\"
.if \\n[hd*level]>1 .as hd*mark \\n[H2]
.\"
.nr hd*i 2 1
.while \\n+[hd*i]<15 .if \\n[hd*level]>(\\n[hd*i]-1) \
.	as hd*mark .\\n[H\\n[hd*i]]
.if \\n[Ht] .ds hd*mark \\n[H\\n[hd*level]].
.\"
.\" special case, no dot after level one heading if not H1dot true
.if (\\n[hd*level]=1)&(\\n[H1dot]=0) .ds hd*mark \\n[H1]
.\"
.ds hd@mark-trimmed \\*[hd*mark]\" mark without spaces, for references
.as hd*mark \ \ \"	add spaces between heading mark and title
.if !\\n[hd*arg1] .ds hd*mark \" empty; no mark for unnumbered heading
.\"
.if \\n[D]>=2 .tm Heading "\\$2"
.if \\n[D]>=6 .tm \\$0: hd*mark="\\*[hd*mark]"
.nr hd*htype 0			\" hd*htype = check break and space
.				\" 0 = run-in, 1 = break only, 2 = space
.if \\n[hd*level]<=\\n[Hb] .nr hd*htype 1
.if \\n[hd*level]<=\\n[Hs] .nr hd*htype 2
.					\" two spaces if hd*htype == 0
.ie (\\n[hd*htype]=0)&(\w@\\$2@) .ds hd*suf-space "  \" 2 spaces
.el                              .ds hd*suf-space \" empty
.nr hd*need 2v				\" hd*need = header need space
.\"---------- user macro HX ------------
.\" User exit macro to override numbering.
.\" May change hd*mark (}0), hd*suf-space (}2) and hd*need (;3)
.\" Can also change Hps1/2.
.if d HX .HX \\n[hd*level] \\n[hd*arg1] "\\$2\\$3"
.\"--------------------------------------
.\" pre-space
.ie \\n[hd*level]<=\\n[Hps] .SP (u;\\n[Hps2])
.el                         .SP (u;\\n[Hps1])
.\"
.if \\$1=1&\\n[Np] .nr par*Np-counter 0
.if \\$1<3         .nr par*nP-counter 0
.\" start diversion to measure size of header
.debug@di hd*div \" never emitted
\\*[hd*mark]\\$2\\$3\\*[hd*suf-space]
.br
.debug@di
.rm hd*div
.if \\n[hd*htype] .na \"	do not adjust heading if not run-in
.if \\n[hd*htype]<2 .nr hd*need +\\n[Lsp]u \"	add some extra space
.ne \\n[hd*need]u+\\n[dn]u+.5p-1v \"	space needed for a heading
.\"
.\" size and font calculations
.hd@split hd*font \\n[hd*level] HF \\*[HF]\"	get font for this level
.ft \\*[hd*font]\"			set new font
.hd@split hd*new-ps \\n[hd*level] HP \\*[HP]\"	get point size
.ie (\\*[hd*new-ps]=0):(\w@\\*[hd*new-ps]@=0) \{\
.	if \\n[hd*htype] \{\
.		if '\\*[hd*font]'3' \{\
.			ps -1
.			vs -1
.		\}
.		if '\\*[hd*font]'B' \{\
.			ps -1
.			vs -1
.		\}
.	\}
.\}
.el \{\
.	ps \\*[hd*new-ps]
.	vs \\*[hd*new-ps]+2
.\}
.\"
.\"---------- user macro HY -------------
.\"	user macro to reset indents
.if d HY .HY \\n[hd*level] \\n[hd*arg1] "\\$2\\$3"
.\" HTML: mark beginning of heading
.misc@tag NH \\n[hd*level]
.\"--------------------------------------
.nr hd*mark-size \w@\\*[hd*mark]@
.if (\\n[hd*level]<=\\n[Hc])&\\n[hd*htype] .ce\" center if level<=Hc
.\"
.\"	finally, output the header
\\*[hd*mark]\&\c
.\"	and the rest of the header
.ie \\n[hd*htype] \{\
\\$2\\$3
.	br
.\}
.el \\$2\\$3\\*[hd*suf-space]\&\c
.ft 1
.\" restore pointsize and vertical size.
.ps \\n[@ps]u
.vs \\n[@vs]u
.\"
.\" table of contents
.if (\\n[hd*level]<=\\n[Cl])&\w@\\$2@ .toc@entry \\n[hd*level] "\\$2"
.\"	set adjust to previous value
.SA
.\"	do break or space
.if \\n[hd*htype] .br
.if \\n[hd*htype]>1 .SP (u;\\n[Lsp]*\\n[Hss])
.ie \\n[hd*htype] \{\
.	\"	indent if Hi=1 and Pt=1
.	if (\\n[Hi]=1)&(\\n[Pt]=1) .ti +\\n[Pi]n
.	\"	indent size of mark if Hi=2
.	if \\n[hd*htype]&(\\n[Hi]>1) .ti +\\n[hd*mark-size]u
.\}
.\"
.\"	check if it is time to reset footnotes
.if (\\n[hd*level]=1)&\\n[ft*clear-at-header] .nr ft*nr 0 1
.\"
.\"	check if it is time to reset indexes
.if (\\n[hd*level]=1)&\\n[Sectf] \{\
.	nr lix*fg-nr 0 1
.	nr lix*tb-nr 0 1
.	nr lix*ec-nr 0 1
.	nr lix*ex-nr 0 1
.\}
.\"---------- user macro HZ ----------
.if d HZ .HZ \\n[hd*level] \\n[hd*arg1] "\\$2\\$3"
.nr hd*last-pos \\n[nl]
.nr hd*last-hsize \\n[.k]
.\" HTML: end of heading
.misc@tag EO-H
.\" _Any_ output after this heading resets suppression of indentation.
.itc 1 hd*trap
..
.\"--------
.de HM
\\*[debug@dump-args]\\
.nr hd*i 0 1
.while \\n+[hd*i]<15 .af H\\n[hd*i] \\$[\\n[hd*i]] 1
..
.\"----------------------
.\" set page-nr, called from header
.\"
.de hd@set-page
.\"
.ie \\n[.$]>0 .nr P \\$1
.el           .nr P +1
.\" Set section-page-string
.ds hd*sect-pg \\n[H1]-\\n[P]
.if \\n[Sectp]>1 .if '\\n[H1]'0' .ds hd*sect-pg "
..
.\"########### module pg ####################
.\" set end of text trap
.wh 0 pg@header
.em pg@end-of-text
.\"
.ds pg*header ''- \\n[P] -''
.ds pg*footer
.if \n[N]=4 .ds pg*header ''''
.if (\n[N]=3):(\n[N]=5) \{\
.	ds pg*header ''''
.	ds pg*footer ''\\*[hd*sect-pg]''
.\}
.ds pg*even-footer
.ds pg*odd-footer
.ds pg*even-header
.ds pg*odd-header
.\"
.nr pg*top-margin 0
.nr pg*foot-margin 0
.nr pg*below-text-gap 1v
.nr pg*block-size 0
.nr pg*footer-size 6v\"			 1v+footer+even/odd footer+3v
.nr pg*header-size 7v\"			 3v+header+even/odd header+2v
.nr pg*extra-footer-size 0
.nr pg*extra-header-size 0
.nr ft*note-size 0
.nr ft*margin-below 0
.nr pg*cur-column 0
.nr pg*cols-per-page 1
.nr pg*cur-po \n[@po]
.nr pg*head-mark 0
.nr pg*at-end-of-input 0
.\"
.nr pg*ps \n[@ps]
.nr pg*vs \n[@vs]
.\"-------------------------
.\" footer TRAPS: set, enable and disable
.de pg@set-new-trap
.nr pg*foot-trap \\n[@pl]u-(\
\\n[pg*below-text-gap]u+\\n[pg*block-size]u+\
\\n[ft*note-size]u+\\n[ft*margin-below]u+\
\\n[pg*foot-margin]u+\\n[pg*footer-size]u+\
\\n[pg*extra-footer-size]u)
.\"
.if \\n[D]>=6 .tm \\$0: pg*foot-trap=\
\\n[pg*below-text-gap]u+\\n[pg*block-size]u+\
\\n[ft*note-size]u+\\n[ft*margin-below]u+\
\\n[pg*foot-margin]u+\\n[pg*footer-size]u+\
\\n[pg*extra-footer-size]u)=\\n[pg*foot-trap]u
.\"
.\" last-pos points to the position of the footer and bottom
.\" block below foot-notes.
.nr pg*last-pos \\n[@pl]u-(\\n[pg*block-size]u+\
\\n[pg*foot-margin]u+\\n[pg*footer-size]u+\
\\n[pg*extra-footer-size]u)
.if \\n[D]>=6 .tm \\$0: pg*last-pos=\\n[@pl]u-(\\n[pg*block-size]u+\
\\n[pg*foot-margin]u+\\n[pg*footer-size]u+\
\\n[pg*extra-footer-size]u)=\\n[pg*last-pos]u
..
.de pg@enable-trap
.\" Disable in HTML mode
.if !'\*[.T]'html' \{\
.	wh \\n[pg*foot-trap]u pg@footer
.	if \\n[D]>=6 \{\
.		tm \\$0: .t=\\n[.t]u, nl=\\n[nl]u
.		tm Traps:
.		pwh
.	\}
.\}
..
.de pg@disable-trap
.ch pg@footer
..
.\" move to new trap (if changed).
.de pg@move-trap
.pg@disable-trap
.pg@set-new-trap
.pg@enable-trap
..
.de pg@enable-top-trap
.\" set trap for pageheader.
.nr pg*top-enabled 1
..
.de pg@disable-top-trap
.\" remove trap for pageheader.
.nr pg*top-enabled 0
..
.\" no header on the next page
.de PGNH
\\*[debug@dump-args]\\
.nr pg*top-enabled (-1)
..
.\" set first trap for pagefooter
.pg@enable-top-trap
.pg@set-new-trap
.pg@enable-trap
.\"-------------------------
.\" stop output and begin on next page. Fix footnotes and all that.
.de pg@next-page
.\".debug@little-dump next-page
.br
.if \\n[pg*at-end-of-input] \c
.ne 999i	\" activate trap; TODO: use \n[.R]; see Savannah #63587
.\" .pg@footer
..
.\"-------------------------
.\" support for PX, TP and EOP.
.als }t pg*header
.als }e pg*even-header
.als }o pg*odd-header
.als TPh pg*header
.als TPeh pg*even-header
.als TPoh pg*odd-header
.\"
.als }b pg*footer
.als }f pg*even-footer
.als }p pg*odd-footer
.als EOPf pg*footer
.als EOPef pg*even-footer
.als EOPof pg*odd-footer
.\"------------------------------------------------------------
.\" HEADER
.de pg@header
.if \\n[D] .tm Page #\\n[%] (\\n[.F]:\\n[c.])
.\" Disable in HTML mode
.if !'\*[.T]'html' \{\
.	\" We need room for all this plus one line of body text (`.V`).
.	nr pg*required-page-length \
(u;\\n[pg*header-size]    + \\n[pg*extra-header-size] \
 + \\n[pg*footer-size]    + \\n[pg*extra-footer-size] \
 + \\n[pg*below-text-gap] + \\n[.V])
.	if (\\n[pg*required-page-length] > \\n[.p]) \{\
.		pl \\n[nl]u
.		ds pg*msg insufficient page length; need at least
.		as pg*msg " \\n[pg*required-page-length]u,
.		as pg*msg " have \\n[.p]u; aborting
.		@error \\*[pg*msg]
.	\}
.\}
.ie \\n[Hy] .@enable-hyphenation
.el         .nh
.if \\n[Idxf] \{\
.tl '<pagenr\ \\n[%]>'''
.\}
.\" assign current page-number to P
.hd@set-page
.\" reset spacing
.nr line*lp\\n[.z] 0
.nr line*ac\\n[.z] 0
.\"
.\" suppress pageheader if pagenumber == 1 and N == [124]
.if \\n[pg*top-enabled] \{\
.\"	must be fixed!!
.\".	pg@disable-top-trap
.	if \\n[pg*extra-header-size] 'sp \\n[pg*extra-header-size]u
.	if \\n[pg*top-margin] 'sp \\n[pg*top-margin]u
.	ie d let@header .let@header
.	el \{\
.		ev pg*tl-ev
.		pg@set-env
.		ie d TP .TP
.		el \{\
'			sp 3
.			ds hd*format \\g[P]
.			af P 0
.			ie (\\n[P]=1)&((\\n[N]=1):(\\n[N]=2)) .sp
.			el \{\
.				if \\n[D]>=3 \
.					tm Header "\\*[pg*header]"
.				tl \\*[pg*header]
.			\}
.			af P \\*[hd*format]
.			ie o \{\
.				if \\n[D]>=3 \
.					tm Header "\\*[pg*odd-header]"
.				tl \\*[pg*odd-header]
.			\}
.			el \{\
.				if \\n[D]>=3 \
.					tm Header "\\*[pg*even-header]"
.				tl \\*[pg*even-header]
.			\}
'			sp 2
.		\}
.		ev
.	\}
.	\" why no-space??
.	if d PX \{\
.		ns
.		PX
.		rs
.	\}
.	\" check for pending footnotes
.	ft@check-old
.	\"
.	\" back to normal text processing
.	pg@enable-trap
.	\" mark for multicolumn
.	nr pg*head-mark \\n[nl]u
.	\" reset NCOL pointer at each new page.
.	nr pg*last-ncol 0
.	\" set multicolumn
.	\"
.	pg@set-po
.	\" print floating displays
.	df@print-float 4
.	tbl@top-hook
.	ns
.\}
.if \\n[pg*top-enabled]<0 .nr pg*top-enabled 1
.nr hd*cur-bline \\n[nl]	\" .H needs to know if output has occurred
.\}
..
.\"---------------------------------------------------------
.\" FOOTER
.de pg@footer
.ec
.if \\n[D]>=3 \{\
.	ie !\\n[pg*at-end-of-input] .tm End of page #\\n% \
(\\n[.F]:\\n[c.])
.	el                          .tm End of page #\\n%
.\}
.if \\n[D]>=6 .tm \\$0: nl=\\n[nl]u
.pg@disable-trap
.\".debug@little-dump footer
.tbl@bottom-hook
.\" increment pageoffset for MC
.\" move to the exact start of footer.
'sp |\\n[pg*foot-trap]u+1v
.\"
.if \\n[D]>=6 .tm FOOTER after .sp, nl=\\n[nl]u
.\" print footnotes
.if d ft*div .ft@print
.\"
.pg@inc-po
.if !\\n[pg*cur-column] .pg@print-footer
.\" next column
.pg@set-po
.pg@enable-trap
.if \\n[@in-verbatim-region] .eo
..
.\"-------------------------
.de pg@print-footer
.\" jump to the position just below the foot-notes.
'sp |\\n[pg*last-pos]u+1v
.if \\n[D]>=6 .tm \\$0: nl=\\n[nl]u
.\" check if there are any bottom block
.if d pg*block-div .pg@block
.\"
.\" print the footer and eject new page
.ev pg*tl-ev
.pg@set-env
.vpt 0
.\" user defined end-of-page macro
.ie d EOP \{\
.	if \\n[D]>=5 .tm \\$0: calling user-defined EOP macro
.	EOP
.\}
.el \{\
.	ie o \{\
.		if \\n[D]>=3 .tm Footer "\\*[pg*odd-footer]"
.		tl \\*[pg*odd-footer]
.	\}
.	el \{\
.		if \\n[D]>=3 .tm Footer "\\*[pg*even-footer]"
.		tl \\*[pg*even-footer]
.	\}
.	ds hd*format \\g[P]
.	af P 0
.	ie (\\n[P]=1)&(\\n[N]=1) \{\
.		if \\n[D]>=3 .tm Footer "\\*[pg*header]" \" that's right
.		tl \\*[pg*header]
.	\}
.	el \{\
.		if \\n[D]>=3 .tm Footer "\\*[pg*footer]"
.		tl \\*[pg*footer]
.	\}
.	af P \\*[hd*format]
.	tl ''\\*[Pg_type!\\n[@copy_type]]''
.\}
.vpt 1
.ev
.\" be sure that floating displays and footnotes will be
.\" printed at the end of the document.
.ie (\\n[df*fnr]>=\\n[df*o-fnr]):\\n[ft*exist] \{\
.	ev ne
'	bp
.	ev
.\}
.el 'bp
..
.\"-------------------------
.\"
.\" Initialize the title environment
.de pg@set-env
.na
.nh
'in 0
'ti 0
.ie \\n[Pgps] \{\
.	ps \\n[@ps]u
.	vs \\n[@vs]u
.\}
.el \{\
.	ps \\n[pg*ps]u
.	vs \\n[pg*vs]u
.\}
.lt \\n[@ll]u
.ll \\n[@ll]u
..
.\"-------------------------
.de PH
\\*[debug@dump-args]\\
.ds pg*header "\\$1
.pg@set-new-size
..
.de PF
\\*[debug@dump-args]\\
.ds pg*footer "\\$1
.pg@set-new-size
..
.de OH
\\*[debug@dump-args]\\
.ds pg*odd-header "\\$1
.pg@set-new-size
..
.de EH
\\*[debug@dump-args]\\
.ds pg*even-header "\\$1
.pg@set-new-size
..
.de OF
\\*[debug@dump-args]\\
.ds pg*odd-footer "\\$1
.pg@set-new-size
..
.de EF
\\*[debug@dump-args]\\
.ds pg*even-footer "\\$1
.pg@set-new-size
..
.de pg@clear-hd
.ds pg*even-header
.ds pg*odd-header
.ds pg*header
..
.de pg@clear-ft
.ds pg*even-footer
.ds pg*odd-footer
.ds pg*footer
..
.de pg@set-new-size
.nr pg*ps \\n[@ps]
.nr pg*vs \\n[@vs]
.pg@move-trap
..
.\"-------------------------
.\" end of page processing
.de pg@footnotes
.\".debug@little-dump footnotes
.\" output footnotes. set trap for block
.\"
..
.\"-------------------------
.\" print bottom block
.de pg@block
.ev pg*block-ev
'nf
'in 0
.ll 100i
.debug@emit pg*block-div
.br
.ev
..
.\"-------------------------
.\" define bottom block
.de BS
\\*[debug@dump-args]\\
.misc@ev-keep pg*block-ev
.@reset
.debug@box pg*block-div
..
.\"-------------------------
.de BE
\\*[debug@dump-args]\\
.br \" in case the user forgot
.debug@box
.nr pg*block-size \\n[dn]u
.ev
.pg@move-trap
..
.\"-------------------------
.\" print out all pending text
.de pg@end-of-text
.if \\n[D]>=5 .tm \\$0: end-of-input macro: shutting down
.if \\n[D]>=4 .tm End of document text
.nr pg*at-end-of-input 1
.\" XXX: What about spilled footnotes?
.df@eot-print
.ref@eot-print
..
.\"-------------------------
.\" set top and bottom margins
.\" -T	sets pg*footer-size and pg*header-size instead
.de VM
\\*[debug@dump-args]\\
.ie '\\$1'-T' \{\
.	shift
.	if \\n[.$]=0 \{\
.		nr pg*footer-size 5v
.		nr pg*header-size 7v
.	\}
.	if \\n[.$]>0 .nr pg*header-size (v;\\$1)
.	if \\n[.$]>1 .nr pg*footer-size (v;\\$2)
.\}
.el \{\
.	if \\n[.$]=0 \{\
.		nr pg*extra-footer-size 0
.		nr pg*extra-header-size 0
.	\}
.	if \\n[.$]>0 .nr pg*extra-header-size (v;\\$1)
.	if \\n[.$]>1 .nr pg*extra-footer-size (v;\\$2)
.	if \\n[D]>=6 \{\
.		tm \\$0: extra top \\n[pg*extra-footer-size]
.		tm \\$0: extra bottom \\n[pg*extra-header-size]
.	\}
.\}
.pg@move-trap
..
.\"---------------------
.\" multicolumn output.
.de pg@set-po
.if \\n[pg*cols-per-page]>1 \{\
.	ll \\n[pg*column-size]u
.\}
..
.de pg@inc-po
.if \\n[pg*cols-per-page]>1 \{\
.	ie \\n+[pg*cur-column]>=\\n[pg*cols-per-page] \{\
.		nr pg*cur-column 0 1
.		nr pg*cur-po \\n[@po]u
.		po \\n[@po]u
.		ll \\n[@ll]u
.	\}
.	el \{\
.		nr pg*cur-po +(\\n[pg*column-size]u+\\n[pg*column-sep]u)
.		po \\n[pg*cur-po]u
'		sp |\\n[pg*head-mark]u
.		tbl@top-hook
.	\}
.\}
..
.\" An argument disables the page-break.
.de 1C
\\*[debug@dump-args]\\
.if \\n[pg*cols-per-page]<=1 \{\
.	@warning \\$0: multicolumn mode not active
.	return
.\}
.br
.nr pg*cols-per-page 1
.nr pg*column-sep 0
.nr pg*column-size \\n[@ll]
.nr pg*ncol-i \\n[pg*cur-column]\"	temp variable
.nr pg*cur-column 0 1
.nr pg*cur-po \\n[@po]u
.PGFORM
.ie !'\\$1'1' .SK
.el \{\
.	if d ft*div \{\
.		if \\n[pg*ncol-i]>0 \{\
.			@warning \\$0: returning to single-column \
layout with suppressed page break and footnote pending; output may be \
messy
.		\}
.	\}
.	if \\n[pg*last-ncol]>0 \{\
.		sp |\\n[pg*last-ncol]u
.		nr pg*last-ncol 0
.	\}
.\}
..
.de 2C
\\*[debug@dump-args]\\
.if \\n[pg*cols-per-page]>1 .@error \\$0: multicolumn mode already \
active
.br
.nr pg*head-mark \\n[nl]u
.nr pg*cols-per-page 2
.nr pg*column-sep \\n[@ll]/15
.nr pg*column-size (\\n[@ll]u*7)/15
.nr pg*cur-column 0 1
.nr pg*cur-po \\n[@po]u
.ll \\n[pg*column-size]u
.\" .lt \\n[pg*column-size]u
..
.\" MC column-size [ column-separation ]
.de MC
\\*[debug@dump-args]\\
.if \\n[pg*cols-per-page]>1 .@error \\$0: multicolumn mode already \
active
.br
.nr pg*head-mark \\n[nl]u
.ie ''\\$1' .nr pg*column-size \\n[.l]
.el         .nr pg*column-size (n;\\$1)
.ie ''\\$2' .nr pg*column-sep \\n[pg*column-size]/15
.el         .nr pg*column-sep (n;\\$2)
.\"
.\" calculate the number of columns/page
.nr pg*cols-per-page 0 \" temporarily invalid!
.nr pg*i \\n[pg*column-size]
.while \\n[pg*i]<=\\n[.l] \{\
.	nr pg*cols-per-page +1
.	nr pg*i \\n[pg*i]+\\n[pg*column-sep]+\\n[pg*column-size]
.\}
.if \\n[pg*cols-per-page]<0 .@abort \\n[pg*cols-per-page] columns in \
page
.nr pg*cur-column 0 1
.nr pg*cur-po \\n[@po]u
.ll \\n[pg*column-size]u
.\" .lt \\n[pg*column-size]u
..
.\" begin a new column if using `2C` or `MC`
.de NCOL
\\*[debug@dump-args]\\
.if \\n[pg*cols-per-page]<2 .@warning \\$0: not in multi-column mode; \
breaking page
.br
.if \\n[nl]>\\n[pg*last-ncol] .nr pg*last-ncol \\n[nl]
.pg@footer
..
.\" skip pages
.de SK
\\*[debug@dump-args]\\
.br
.bp
.nr pg*i 0 1
.\" force new page by writing something invisible.
.while \\n+[pg*i]<=(0\\$1) \{\
\&
.	bp
.\}
..
.\"-------------------------------
.\" MULB width1 space1 width2 space2 width3 space3 ...
.de MULB
\\*[debug@dump-args]\\
.br
.nr pg*i 0 1
.nr pg*mul-x 0 1
.nr pg*mul-ind 0
.nr pg*mul-last 0
.while \\n[.$] \{\
.	nr pg*mul!\\n+[pg*i] (n;0\\$1)
.	nr pg*muls!\\n[pg*i] (n;0\\$2)
.	shift 2
.\}
.nr pg*mul-max-col \\n[pg*i]
.ds pg*mul-fam \\n[.fam]
.nr pg*mul-font \\n[.f]
.ev pg*mul-ev
.ps \\n[@ps]u
.vs \\n[@vs]u
.fam \\*[pg*mul-fam]
.ft \\n[pg*mul-font]
.fi
.@enable-hyphenation
.debug@di pg*mul-div
.MULN
..
.\"-----------
.de MULN
\\*[debug@dump-args]\\
.if \\n[pg*cols-per-page]<2 .@error \\$0: not in multi-column mode
.if \\n[pg*mul-x]>=\\n[pg*mul-max-col] \{\
.	ds pg*msg .@abort undefined column width \"
.	as pg*msg (pg*mul-x=\\n[pg*mul-x] >= \
pg*mul-max-col=\\n[pg*mul-max])\"
.	@abort \\*[pg*msg]
.\}
.br
.if \\n[.d]>\\n[pg*mul-last] .nr pg*mul-last \\n[.d]
.rt +0
.in \\n[pg*mul-ind]u
.ll (u;\\n[.i]+\\n[pg*mul!\\n+[pg*mul-x]])u
.nr pg*mul-ind +(u;\\n[pg*mul!\\n[pg*mul-x]]+\\n[pg*muls!\\n[pg*mul-x]])
..
.\"-----------
.\" MULE
.de MULE
\\*[debug@dump-args]\\
.br
.if \\n[.d]>\\n[pg*mul-last] .nr pg*mul-last \\n[.d]
.debug@di
.ev
.ne \\n[pg*mul-last]u
.nf
.mk
.debug@emit pg*mul-div
.rt
.sp \\n[pg*mul-last]u
.fi
..
.\"-----------
.de OP
\\*[debug@dump-args]\\
.br
.ie o .if !\\n[pg*head-mark]=\\n[nl] \{\
.	bp +1
.	bp +1
.\}
.el .bp
..
.\"########### module footnotes ###################
.nr ft*note-size 0
.nr ft*busy 0
.nr ft*nr 0 1
.aln Ftnum ft*nr
.aln :p ft*nr		\" for DWB mm compatibility
.nr ft*wide 0
.nr ft*hyphen 0\"	hyphenation value
.nr ft*adjust 1\"	>0 if adjust true
.nr ft*indent 1\"	>0 if text indent true (not imp. $$$)
.nr ft*just 0\"	0=left justification, 1=right (not imp. $$$)
.nr ft*exist 0\"	not zero if there are any footnotes to be printed
.nr ft*clear-at-header 0\" >0 if footnotes should be reset at first level head.
.\"
.ie t .ds F \v'-.4m'\s-3\\n+[ft*nr]\s0\v'.4m'
.el   .ds F [\\n+[ft*nr]]
.\"
.\"-----------------
.\" init footnote environment
.de ft@init
.\" indentcontrol not implemented $$$
.\" label justification not implemented $$$
'in 0
'fi
.ie \\n[ft*adjust] .ad
.el                .na
.ie \\n[ft*hyphen] .@enable-hyphenation
.el                .hy 0
.ll \\n[@cur-ll]u
.lt \\n[@cur-ll]u
.ps (p;\\n[@ps]u-2)
.vs (p;\\n[@vs]u-1)
..
.\"-----------------
.\" set footnote format
.\" no support for two column processing (yet). $$$
.de FD
\\*[debug@dump-args]\\
.if \\n[.$]=0 .@error \\$0: expected 1 or 2 arguments, got \\n[.$]
.ie \\n[.$]=2 .nr ft*clear-at-header 1
.el           .nr ft*clear-at-header 0
.\"
.if !'\\$1'' \{\
.	ie \\$1>11 .nr ft*format 0
.	el .nr ft*format \\$1
.	\"
.	nr ft*hyphen (\\n[ft*format]%2)*6
.	nr ft*format \\n[ft*format]/2
.	\"
.	nr ft*adjust 1-(\\n[ft*format]%2)
.	nr ft*format \\n[ft*format]/2
.	\"
.	nr ft*indent 1-(\\n[ft*format]%2)
.	nr ft*format \\n[ft*format]/2
.	\"
.	nr ft*just \\n[ft*format]%2
.\}
..
.\"---------------
.\" Footnote and display width control $$$
.de WC
\\*[debug@dump-args]\\
.nr ft*i 0 1
.while \\n+[ft*i]<=\\n[.$] \{\
.	ds ft*x \\$[\\n[ft*i]]
.	if '\\*[ft*x]'N' \{\
.		nr ft*wide 0
.		nr ft*first-fn 0
.		nr ds*wide 0
.		nr ds*float-break 1
.	\}
.	if '\\*[ft*x]'-WF' .nr ft*wide 0
.	if '\\*[ft*x]'WF' .nr ft*wide 1
.	if '\\*[ft*x]'-FF' .nr ft*first-fn 0
.	if '\\*[ft*x]'FF' .nr ft*first-fn 1
.	if '\\*[ft*x]'-WD' \{\
.		nr ds*wide 0
.		if r ft*df-save \{\
.			nr Df \\n[ft*df-save]
.			rm ft*df-save
.		\}
.	\}
.	if '\\*[ft*x]'WD' \{\
.		nr ds*wide 1
.		nr ft*df-save \\n[Df]
.		nr Df 4
.	\}
.	if '\\*[ft*x]'-FB' .nr ds*float-break 0
.	if '\\*[ft*x]'FB' .nr ds*float-break 1
.	if \\n[D]>=6 .tm \\$0: WF=\\n[ft*wide] WD=\\n[ds*wide]
.\}
..
.\"-----------------
.\" begin footnote
.\" Change environment, switch to diversion and print the foot-note mark.
.de FS
\\*[debug@dump-args]\\
.if \\n[ft*busy] .@error \\$0: cannot nest; missing FE?
.nr ft*busy 1
.ev ft*ev
.ft@init
.if !\\n[ft*wide] .pg@set-po
.debug@di ft*tmp-div
.nr ft*space (u;\\n[Fs]*\\n[Lsp])
.sp \\n[ft*space]u
.\" print mark
.ie \\n[.$] .ds ft*mark \\$1
.el         .ds ft*mark \\n[ft*nr].
\\*[ft*mark]
.in +.75c
.sp -1
.nr ft*exist 1
..
.\"-----------------
.\" init footnote diversion
.de ft@init-footnote
.debug@di ft*div
.\" Use the em dash to draw the rule in nroff mode, since terminal
.\" devices generally don't have a baseline rule glyph.  The "low line"
.\" descends below the baseline and terminal fonts generally don't have
.\" it span the character cell completely.  (A Unicode font might do so
.\" for the em dash; we make a best-effort attempt to look pleasant.)
.ie t .nop \l'20n'
.el   .nop \l'20n\[em]'
.br
.debug@di
.nr ft*note-size \\n[dn]
..
.\"-----------------
.\" end footnote
.\" End the diversion, back to previous environment, and adjust
.\" the trap to the new foot-note size.
.de FE
\\*[debug@dump-args]\\
.nr ft*busy 0
.br
.debug@di
'in 0
'nf
.if \\n[@pl]u<\\n[dn]u .@error \\$0: footnote bigger than page area
.if !d ft*div .nr dn +1v
.if \\n[D]>=6 .tm \\$0: foot-trap=\\n[pg*foot-trap] .d=\\n[.d] \
dn=\\n[dn]
.ie (\\n[pg*foot-trap]u-\\n[.d]u)<\\n[dn]u \{\
.	debug@da ft*next-div
.	debug@emit ft*tmp-div
.	br
.	debug@di
.\}
.el \{\
.	if !d ft*div .ft@init-footnote
.	debug@da ft*div
.	debug@emit ft*tmp-div
.	debug@di
.	nr ft*note-size +\\n[dn]
.	nr ft*margin-below 1v
.\}
.rm ft*tmp-div
.ev
.pg@move-trap
..
.\"-----------------
.\" print footnotes, see pg@footer
.de ft@print
.ev ft*print-ev
'nf
'in 0
.ll 100i
.if \\n[D]>=2 .tm Footnote(s)
.debug@emit ft*div
.br
.ev
.rm ft*div
.nr ft*note-size 0
.pg@move-trap
..
.\"-----------------
.\" check if any pending footnotes, see pg@header
.de ft@check-old
.ie d ft*next-div \{\
.	ev ft*ev
.	ft@init
.	ft@init-footnote
.	nf
.	in 0
.	debug@da ft*div
.	debug@emit ft*next-div
.	debug@di
.	nr ft*note-size +\\n[dn]
.	rm ft*next-div
.	ev
.	nr ft*exist 0
.	pg@move-trap
.\}
.el \{\
.	nr ft*margin-below 0
.	pg@move-trap
.\}
..
.\"########### module display ###################
.nr ds*wide 0\"		>0 if wide displays wanted
.nr df*fnr 0 1\"	floating display counter
.nr df*o-fnr 1\"	floating display counter, already printed
.nr ds*snr 0 1\"	static display counter
.nr ds*lvl 0 1\"	display level
.nr ds*float-busy 0\"	>0 if printing float
.nr df*float 0\"	>0 if previous display was floating
.\"--------------------------------------------
.de DE
\\*[debug@dump-args]\\
.ie \\n[df*float] .df@end \\$@
.el               .ds@end \\$@
..
.\"--------------------------------------------
.\" floating display start
.\" nested DF/DE is not allowed.
.de DF
\\*[debug@dump-args]\\
.if \\n[df*float] \{\
.	ds df*msg \\$0: cannot nest floating displays;\"
.	as df*msg " use DS within DF/DE\"
.	@error \\*[df*msg]
.\}
.ds ds@macro \\$0
.ds@set-format \\$@
.\"
.nr df*old-ll \\n[.l]
.nr ds*ftmp \\n[.f]
.misc@ev-keep df*ev
.ft \\n[ds*ftmp]
.\"
.@reset
.debug@di df*div
'in 0
.\"
.ds@set-new-ev \\n[df*old-ll]
.SP \\n[Lsp]u
.nr df*float 1
..
.\"--------------------------------------------
.de df@end
.br
.SP \\n[Lsp]u
.debug@di
.nr df*width!\\n+[df*fnr] \\n[dl]
.nr df*height!\\n[df*fnr] \\n[dn]
.nr df*wide!\\n[df*fnr] \\n[ds*wide]
.nr df*format!\\n[df*fnr] \\n[ds*format]
.ev
.if \\n[D]>=6 .tm \\$0: fnr=\\n[df*fnr] w=\\n[dl] h=\\n[dn] \
wide=\\n[ds*wide] form=\\n[ds*format]
.\"	move div to the floating display list
.rn df*div df*fdiv!\\n[df*fnr]
.\"
.nr par@suppress-indentation 1	\" no indentation after displays
.\" print float if queue is empty and the display fits into
.\" the current page
.if (\\n[df*fnr]>=\\n[df*o-fnr])&(\\n[dn]<\\n[.t]) .df@print-float 1
.nr df*float 0
..
.\"-------------
.\" called by end-of-text
.de df@eot-print
.br
.if \\n[df*o-fnr]<=\\n[df*fnr] \{\
.	if \\n[D]>=2 .tm Floating display(s)
.\" still some floats left, make non-empty environment
.	misc@ev-keep ne
.	@reset
\c
.	df@print-float 3
.	ev
.\}
..
.\"---------------
.\" print according to Df and De.
.\" .df@print-float type
.\"	type	called from
.\"	1	.DE
.\"	2	end of section
.\"	3	end of document
.\"	4	beginning of new page
.\"
.de df@print-float
.if \\n[Df]>5 .@abort invalid float type: 5 < Df (\\n[Df])
.if !\\n[ds*float-busy] \{\
.	nr ds*float-busy 1
.\" at .DE
.	if \\n[D]>=6 \{\
.		tmc \\$0: .t=\\n[.t]u
.		if r df*height!\\n[df*o-fnr] \
.			tmc , h=\\n[df*height!\\n[df*o-fnr]]u
.		tm
.	\}
.	\" Df = 1 or 5
.	if (\\$1=1)&((\\n[Df]=1):(\\n[Df]=5)) \{\
.		if \\n[.t]>\\n[df*height!\\n[df*o-fnr]] \{\
.			\" Print only new displays.
.			if \\n[df*o-fnr]=\\n[df*fnr] \{\
.				br
.				ds@print-one-float
.			\}
.		\}
.	\}
.	\" Df = 3
.	if (\\$1=1)&(\\n[Df]=3) \{\
.		if \\n[.t]>\\n[df*height!\\n[df*o-fnr]] \{\
.			br
.			ds@print-one-float
.		\}
.	\}
.\" print all if Df<2 and end of section
.	if (\\$1=2)&(\\n[Sectp]>0)&(\\n[Df]<2) \{\
.		br
.		ds@print-all-floats
.	\}
.\" print all if end of document. Where should they go instead?
.	if \\$1=3 \{\
.		br
.		ds@print-all-floats
.\}
.\" new page
.	if (\\$1=4)&(\\n[Df]>1) \{\
.		if \\n[Df]=2 .ds@print-one-float
.		if \\n[Df]=3 .ds@print-one-float
.		if \\n[Df]>3 \{\
.			ie \\n[De] .ds@print-all-floats
.			el .ds@print-this-page
.		\}
.	\}
.	nr ds*float-busy 0
.\}
..
.\"---------------
.\" DF out
.\" print a floating diversion
.de ds@output-float
.nr df*old-ll \\n[.l]
.nr df*old-in \\n[.i]
.ev ds*fev
.nf
.nr df*i \\n[df*o-fnr]
.nr df*f \\n[df*format!\\n[df*i]]
.\"
.in \\n[df*old-in]u
.if \\n[df*f]=1  'in +\\n[Si]n
.if \\n[df*f]>=2 'in 0
.if \\n[df*f]=2  'ce \\n[.R]
.if \\n[df*f]=3  'in (u;(\\n[.l]-\\n[df*width!\\n[df*i]])/2)
.if \\n[df*f]=4  'rj \\n[.R]
.if \\n[df*f]=5  'in (u;\\n[.l]-\\n[df*width!\\n[df*i]])
.\"
.\"
.debug@emit df*fdiv!\\n[df*o-fnr]
.\"
.if \\n[df*f]=2 'ce 0
.if \\n[df*f]=4 'rj 0
.ev
.rm df*fdiv!\\n[df*i]
.rm df*height!\\n[df*i]
.rm df*format!\\n[df*i]
.if \\n[df*wide!\\n[df*i]] .nr pg*head-mark \\n[nl]u
.nr df*o-fnr +1
..
.\"---------------
.\" print one floating display if there is one.
.de ds@print-one-float
.if \\n[df*o-fnr]<=\\n[df*fnr] \{\
.	if \\n[D]>=6 .tm \\$0: .t=\\n[.t], \
h=\\n[df*height!\\n[df*o-fnr]]
.	if \\n[.t]<\\n[df*height!\\n[df*o-fnr]] .pg@next-page
.	ds@output-float
.	if \\n[De] .pg@next-page
.\}
..
.\"---------------
.\" print all queued floats.
.\" if De>0 do a page eject between the floats.
.de ds@print-all-floats
.while \\n[df*o-fnr]<=\\n[df*fnr] \{\
.	if \\n[D]>=6 .tm \\$0: .t=\\n[.t], \
h=\\n[df*height!\\n[df*o-fnr]]
.	if \\n[.t]<\\n[df*height!\\n[df*o-fnr]] .pg@next-page
.	br
\c
.	ds@output-float
.	if \\n[De] .pg@next-page
.\}
..
.\"---------------
.\" print as many floats as will fit on the current page
.de ds@print-this-page
.while \\n[df*o-fnr]<=\\n[df*fnr] \{\
.	if \\n[D]>=6 .tm \\$0-this-page: .t=\\n[.t], \
h=\\n[df*height!\\n[df*o-fnr]]
.	if \\n[.t]<\\n[df*height!\\n[df*o-fnr]] .break
.	ds@output-float
.\}
..
.\"---------------------------------------------------
.\" get format of the display
.de ds@set-format
.ie \\n[.$] \{\
.	ie r ds*format!\\$1 .nr ds*format \\n[ds*format!\\$1]
.	el .@error \\*[ds@macro]: unrecognized format '\\$1'
.\}
.el .nr ds*format 0
.if \\n[D]>=6 .tm \\$0: ds*format=\\n[ds*format]
.\" fill or not to fill, that is the...
.nr ds*fill 0
.if \\n[.$]>1 \{\
.	ie r ds*fill!\\$2 .nr ds*fill \\n[ds*fill!\\$2]
.	el .@error \\*[ds@macro]: unrecognized fill style '\\$2'
.\}
.if \\n[D]>=6 .tm \\$0: ds*fill=\\n[ds*fill]
.nr ds*rindent 0
.if \\n[.$]>2 .nr ds*rindent (n;\\$3)
.if \\n[D]>=6 .tm \\$0: ds*rindent=\\n[ds*rindent]
..
.\"-----------------------------
.\" .ds@set-new-ev previous-line-length
.de ds@set-new-ev
.ll \\$1u
.lt \\$1u
.if \\n[ds*rindent] \{\
.	ll -\\n[ds*rindent]n
.	lt -\\n[ds*rindent]n
.\}
.if \\n[ds*wide] \{\
.	ll \\n[@ll]u
.	lt \\n[@ll]u
.\}
.\"
.ie \\n[ds*fill] 'fi
.el              'nf
..
.\"--------------------------------------------------------
.nr ds*format 0\"	dummy value for .En/.EQ
.nr ds*format! 0\"	no indent
.nr ds*format!0 0\"	no indent
.nr ds*format!L 0\"	no indent
.nr ds*format!I 1\"	indent
.nr ds*format!1 1\"	indent
.nr ds*format!C 2\"	center each line
.nr ds*format!2 2\"	center each line
.nr ds*format!CB 3\"	center as block
.nr ds*format!3 3\"	center as block
.nr ds*format!R 4\"	right justify each line
.nr ds*format!4 4\"	right justify each line
.nr ds*format!RB 5\"	right justify as block
.nr ds*format!5 5\"	right justify as block
.\"---------------
.nr ds*fill! 0\"	no fill
.nr ds*fill!N 0\"	no fill
.nr ds*fill!0 0\"	no fill
.nr ds*fill!F 1\"	fill on
.nr ds*fill!1 1\"	fill on
.\"--------------------------------------------
.\" static display start
.\" nested DS/DE is allowed. No limit on depth.
.de DS
\\*[debug@dump-args]\\
.ds ds@macro \\$0
.br
.nr ds*lvl +1
.ds@set-format \\$@
.\"
.nr ds*old-ll \\n[.l]
.nr ds*old-in \\n[.i]
.misc@push ds-in \\n[ds*old-in] \" Saving indent and line length of
.misc@push ds-ll \\n[ds*old-ll] \" the text outside the display.
.misc@push ds-form \\n[ds*format]
.nr ds*i \\n[.i]
.nr ds*ftmp \\n[.f]
.misc@ev-keep ds*ev!\\n+[ds*snr]
.ft \\n[ds*ftmp]
.\"
.@reset
.\" indent in a diversion doesn't seem like a good idea.
'in 0
.debug@di ds*div!\\n[ds*snr]
.\"
.nr ds*div-ll \\n[ds*old-ll]
.if \\n[ds*format]=1 .nr ds*div-ll -\\n[Si]n
.ds@set-new-ev \\n[ds*div-ll]
.nr df*float 0
..
.\"--------------------------------------------
.de ds@end
.\" We hard-code the DE macro name here since this macro is internal but
.\" only DE calls it.  We also know we're closing a static display
.\" because df@end is called otherwise.  See `DE`.
.if \\n-[ds*lvl]<0 .@error DE: no corresponding DS
.br
.debug@di
.\" **********
.nr ds*width \\n[dl]
.nr ds*height \\n[dn]
.misc@pop-nr ds-ll ds*old-ll \" Restore indent and
.misc@pop-nr ds-in ds*old-in \" line length
.misc@pop-nr ds-form ds*format
.\"
.\" **********
'nf
.\" calculate needed space
.nr ds*need \\n[ds*height]
.nr ds*i \\n[pg*foot-trap]-\\n[pg*header-size]u-\\n[pg*extra-header-size]u
.if (\\n[ds*height]>\\n[ds*i])&(\\n[.t]<(\\n[ds*i]/2)) .nr ds*need \\n[.t]u+1v
.if (\\n[ds*height]<\\n[ds*i])&(\\n[.t]<(\\n[ds*height])) .nr ds*need \\n[.t]u+1v
.\"	Eject page if display will fit one page and
.\"	there are less than half of the page left.
.if \\n[ds*need] .ne \\n[ds*need]u
.\"
.\"	Print static display
.nr ds*i \\n[Lsp]
.if r Dsp .nr ds*i \\n[Dsp]
.\"
.if \\n[Ds] .SP \\n[ds*i]u \" Space before display
.\" check if pending equation label
.eq@check \\n[ds*need]
'in \\n[ds*old-in]u
.if \\n[ds*format]=1  'in \\n[ds*old-in]u+\\n[Si]n
.if \\n[ds*format]>=2 'in 0
.if \\n[ds*format]=2  'ce \\n[.R]
.if \\n[ds*format]=3  'in (u;(\\n[.l]-\\n[ds*width])/2)
.if \\n[ds*format]=4  'rj \\n[.R]
.if \\n[ds*format]=5  'in (u;\\n[.l]-\\n[ds*width])
.\" **********
.\"
.debug@emit ds*div!\\n[ds*snr]
.if \\n[Ds] .SP \\n[ds*i]u \" Space after display
.\"
.if \\n[ds*format]=2 'ce 0
.if \\n[ds*format]=4 'rj 0
.rm ds*div!\\n[ds*snr]
.nr ds*snr -1
.nr par@suppress-indentation 1	\" no indentation after displays
.ev
..
.\"########### module li ###################
.nr li*tind 0
.nr li*mind 0
.nr li*pad 0
.nr li*type 0
.ds li*mf 0\" mark-or-format
.nr li*li-spc 0
.nr li*lvl 0 1
.aln :g li*lvl
.nr li*cur-vpos 0
.\"--------------------------
.\" .LB text-indent mark-indent pad type [mark [LI-space [LB-space] ] ]
.\"	the major list-begin macro.
.\"	If type is -1, a break occurs.
.de LB
\\*[debug@dump-args]\\
.if \\n[.$]<4 .@error \\$0: expected at least 4 arguments, got \\n[.$]
.misc@push cind \\n[.i]
.misc@push tind \\n[li*tind]
.misc@push mind \\n[li*mind]
.misc@push pad \\n[li*pad]
.misc@push type \\n[li*type]
.misc@push li-spc \\n[li*li-spc]
.ds li*mark-list!\\n[li*lvl] \\*[li*mf]
.nr li*lvl +1
.\"
.nr li*tind (n;0\\$1)\"			text-indent
.nr li*mind (n;0\\$2)\"			mark-indent
.nr li*pad (n;0\\$3)\"			pad
.nr li*type 0\\$4\"			type (in range -1..6)
.ds li*mf \\$5\"			mark-or-format
.ie !'\\$6'' .nr li*li-spc \\$6\"	LI-space
.el          .nr li*li-spc 1
.ie !'\\$7'' .nr li*lb-spc \\$7\"	LB-space
.el          .nr li*lb-spc 0
.\" init listcounter
.nr li*cnt!\\n[li*lvl] 0 1
.nr li*mf-is-mark 1
.if \\n[li*type] \{\
.	nr li*mf-is-mark 0
.	if '\\*[li*mf]'' .ds li*mf 0\"
.	nr li*is-format-valid 0
.	if '\?\\*[li*mf]\?'\?a\?'           .nr li*is-format-valid 1
.	if '\?\\*[li*mf]\?'\?A\?'           .nr li*is-format-valid 1
.	if '\?\\*[li*mf]\?'\?i\?'           .nr li*is-format-valid 1
.	if '\?\\*[li*mf]\?'\?I\?'           .nr li*is-format-valid 1
.	if \B'\\*[li*mf]' .if \\*[li*mf]>-1 .nr li*is-format-valid 1
.	if !\\n[li*is-format-valid] \{\
.		ds li*msg \\$0: type argument is \\n[li*type]\"
.		as li*msg " but mark argument '\\*[li*mf]'\"
.		as li*msg " is not a valid register format;\"
.		as li*msg " assuming '0'\"
.		@warning \\*[li*msg]
.		rm li*msg
.		ds li*mf 0\"
.		\}
.	\}
.\}
.ie \\n[li*mf-is-mark] .af li*cnt!\\n[li*lvl] 0
.el                    .af li*cnt!\\n[li*lvl] \\*[li*mf]
.rr li*mf-is-mark
.\"
.if \\n[li*lb-spc] .SP (u;\\n[li*lb-spc]*\\n[Lsp])
.in +\\n[li*tind]u
..
.\"---------------
.de LI
\\*[debug@dump-args]\\
.if \\n[li*lvl]<1 .@error \\$0: no list active; call AL, BL, BVL, DL, \
ML, RL, VL, or LB first
.if \\n[li*li-spc]&(\\n[li*lvl]<=\\n[Ls]) \
.	SP (u;\\n[li*li-spc]*\\n[Lsp])
.ne 2v
.\"
.nr li*cnt!\\n[li*lvl] +1
.if \\n[li*type]=1 .ds li*enumerator \\n[li*cnt!\\n[li*lvl]].
.if \\n[li*type]=2 .ds li*enumerator \\n[li*cnt!\\n[li*lvl]])
.if \\n[li*type]=3 .ds li*enumerator (\\n[li*cnt!\\n[li*lvl]])
.if \\n[li*type]=4 .ds li*enumerator [\\n[li*cnt!\\n[li*lvl]]]
.if \\n[li*type]=5 .ds li*enumerator <\\n[li*cnt!\\n[li*lvl]]>
.if \\n[li*type]=6 .ds li*enumerator {\\n[li*cnt!\\n[li*lvl]]}
.\" Assemble (prefix, prefix padding, and) mark for this item.
.ds li*c-mark \" empty
.nr li*apply-prefix 0
.if \\n[.$]>1 \{\
.	ie \\n[li*type]=0 \{\
.		\" VL and BVL use a dummy character `\&` as the "mark"
.		\" argument to LB, which _formats_ identically to an
.		\" empty string.  We want a comparison of string
.		\" contents instead (otherwise the tag disappears from
.		\" the output), hence `\?`.
.		if !'\?\\*[li*mf]\?'' .nr li*apply-prefix 1
.	\}
.	el .nr li*apply-prefix 1
.	ie \B'\\$2' .nr li*pad-prefix \\$2
.	el \{\
.		ds li*msg \\$0: pad-prefix argument is not numeric:\"
.		as li*msg " '\\$2'\"
.		@error \\*[li*msg]
.	\}
.	\" TODO: Ditch the following in groff 1.25.
.	if \\$2=2 \{\
.		ds li*msg \\$0: second argument is a Boolean;\"
.		as li*msg " treating '2' as '0'\"
.		@warning \\*[li*msg]
.		rm li*msg
.		nr li*pad-prefix 0
.	\}
.\}
.if \\n[li*apply-prefix] \{\
.	as li*c-mark \\$1\"
.	if \\n[li*pad-prefix] .as li*c-mark \ \"
.\}
.rr li*pad-prefix
.rr li*apply-prefix
.\" If only one argument, it replaces the mark (no prefixing).
.ie \\n[.$]=1 .ds li*c-mark \\$1\"
.el \{\
.	ie d li*enumerator    .as li*c-mark \\*[li*enumerator]\"
.	el                    .as li*c-mark \\*[li*mf]\"
.\}
.rm li*enumerator
.\" Determine amount of padding after the mark.
.nr li*c-pad \\n[li*pad]
.\" Compute width of the mark plus the padding after it.
.if \\n[li*type]>=0 \{\
.	nr li*markpad \w'\\*[li*c-mark]'+\\n[li*c-pad]
.	if \\n[li*markpad]>\\n[li*tind] \{\
.		@warning \\$0: overlong mark '\\*[li*c-mark]'
.		\" Force (minimal) item/mark separation.
.		nr li*c-pad 1n
.	rr li*markpad
.	\}
.\}
.\" determine where the text begins
.nr li*text-begin \\n[li*tind]>?(\w@\\*[li*c-mark]@+\\n[li*c-pad])
.\"
.\" determine where the mark begins
.ie !\\n[li*c-pad] .nr li*mark-begin \\n[li*mind]
.el                .nr li*mark-begin \\n[li*text-begin]-\\n[li*c-pad]-\w@\\*[li*c-mark]@
.if !\\n[li*mark-begin] .nr li*mark-begin 0
.\"
.ti -\\n[li*tind]u
.\" no indentation if hanging indent
.if (\w@\\*[li*c-mark]@=0)&((\\n[.$]=0):(\w@\\$1@=0)) .nr li*text-begin 0
.nop \Z@\&\h'\\n[li*mark-begin]u'\\*[li*c-mark]@\h'\\n[li*text-begin]u'\&\c
.if \\n[li*type]=-1 .br
.rr li*c-pad
.rr li*mark-begin
.rr li*text-begin
.rm li*c-mark
..
.\"
.\"-------------
.de li@pop
.nr li*lvl -1
.misc@pop-nr cind li*tmp
.in \\n[li*tmp]u
.misc@pop-nr tind li*tind
.misc@pop-nr mind li*mind
.misc@pop-nr pad li*pad
.misc@pop-nr type li*type
.misc@pop-nr li-spc li*li-spc
.ds li*mf \\*[li*mark-list!\\n[li*lvl]]
..
.de LE
\\*[debug@dump-args]\\
.if \\n[li*lvl]<1 .@error \\$0: no list active; call AL, BL, BVL, ... \
and LI first
.li@pop
.if '\\$1'1' .SP \\n[Lsp]u
.nr par@suppress-indentation 1	\" no indentation after lists
..
.\"-------------
.\"	list status clear.
.\"	terminate all lists to level i
.de LC
\\*[debug@dump-args]\\
.nr li*i 0
.if \\n[.$] \{\
.	ie \B'\\$1' .nr li*i \\$1
.	el          .@error \\$0: argument is not numeric: '\\$1'
.\}
.if \\n[li*i]>\\n[li*lvl] .@error \\$0 invalid argument: \\n[li*i] \
exceeds depth of nested lists (\\n[li*lvl])
.while \\n[li*lvl]>\\n[li*i] .li@pop
.nr par@suppress-indentation 1	\" no indentation after lists
..
.\"-------------
.\" List types `AL` and `RL` combine enumerators with punctuation, and
.\" use register `Li` to determine text indentation.
.\" TODO: Refactor like `ML` to call `LB` in only one place.
.de AL
\\*[debug@dump-args]\\
.if \\n[.$]>3 .@warning \\$0: ignoring excess arguments
.ie \\n[.$]<=1 .LB              \\n[Li] 0 1 1 "\\$1"
.el \{\
.	ie \\n[.$]=2 .LB        0\\$2   0 1 1 "\\$1"
.	el \{\
.		ie !'\\$2'' .LB \\$2    0 1 1 "\\$1" 0 1
.		el          .LB \\n[Li] 0 1 1 "\\$1" 0 1
.	\}
.\}
..
.\" TODO: Refactor like `ML` to call `LB` in only one place.
.de RL
\\*[debug@dump-args]\\
.if \\n[.$]>2 .@warning \\$0: ignoring excess arguments
.if \\n[.$]<1 .LB      \\n[Li] 0 1 4
.if \\n[.$]=1 .LB      0\\$1   0 1 4
.if \\n[.$]=2 \{\
.	ie '\\$1'' .LB \\n[Li] 0 1 4 1 0 1
.	el         .LB 0\\$1   0 1 4 1 0 1
.\}
..
.\" List types `VL` and `BVL` set a user-specified tag (idiomatically a
.\" word or phrase) and use register `Pi` to determine text indentation.
.\" TODO: Refactor like `ML` to call `LB` in only one place.
.de VL
\\*[debug@dump-args]\\
.if \\n[.$]>3 .@warning \\$0: ignoring excess arguments
.ie \\n[.$]<1 .nr li*text-indent \\n[Pi]
.el           .nr li*text-indent \\$1
.ie \\n[.$]<3 .LB 0\\n[li*text-indent] 0\\$2 0 0
.el           .LB 0\\n[li*text-indent] 0\\$2 0 0 \& 0 1
.rr li*text-indent
..
.\" `BVL` always breaks after the tag, so the mark cannot overset.
.\" TODO: Refactor like `ML` to call `LB` in only one place.
.de BVL
\\*[debug@dump-args]\\
.if \\n[.$]>3 .@warning \\$0: ignoring excess arguments
.ie \\n[.$]<1 .nr li*text-indent \\n[Pi]
.el           .nr li*text-indent \\$1
.ie \\n[.$]<3 .LB 0\\n[li*text-indent] 0\\$2 0 -1
.el           .LB 0\\n[li*text-indent] 0\\$2 0 -1 \& 0 1
.rr li*text-indent
..
.\" List types `BL` and `DL` use bullets and em dashes, respectively, as
.\" the item marks, and use register `Pi` to determine text indentation.
.\" TODO: Refactor like `ML` to call `LB` in only one place.
.de BL
\\*[debug@dump-args]\\
.if \\n[.$]>2 .@warning \\$0: ignoring excess arguments
.if \\n[.$]<1 .LB \\n[Pi] 0 1 0 \\*[BU]
.if \\n[.$]=1 .LB 0\\$1 0 1 0 \\*[BU]
.if \\n[.$]=2 \{\
.	ie '\\$1'' .LB \\n[Pi] 0 1 0 \\*[BU] 0 1
.	el         .LB 0\\$1   0 1 0 \\*[BU] 0 1
.\}
..
.\" TODO: Refactor like `ML` to call `LB` in only one place.
.de DL
\\*[debug@dump-args]\\
.if \\n[.$]>2 .@warning \\$0: ignoring excess arguments
.if \\n[.$]<1 .LB \\n[Pi] 0 1 0 \*[EM]
.if \\n[.$]=1 .LB 0\\$1   0 1 0 \*[EM]
.if \\n[.$]=2 \{\
.	ie '\\$1'' .LB \\n[Pi] 0 1 0 \*[EM] 0 1
.	el         .LB 0\\$1   0 1 0 \*[EM] 0 1
.\}
..
.\" List type `ML` is unlike the other canned list types, which default
.\" their text indentations to either \n[Li] or \n[Pi]; `ML` instead
.\" measures its mark argument to determine text indentation.
.de ML
\\*[debug@dump-args]\\
.if \\n[.$]>3 .@warning \\$0: ignoring excess arguments
.if \\n[.$]<1 .@error \\$0: expected 1 to 3 arguments, got \\n[.$]
.nr li*text-indent \w@\\$1@u+1n
.nr li*pad-amount 0
.if \\n[.$]>1 \{\
.	if !'\\$2'' .ie !\B'\\$2' \{\
.		ds li*msg \\$0: text-indent argument is not numeric:\"
.		as li*msg " '\\$2'\"
.		@error \\*[li*msg]
.	\}
.	el \{\
.		nr li*text-indent (n;\\$2)
.		nr li*pad-amount 1
.	\}
.\}
.ds li*more-args 0 1\"
.if \\n[.$]<3 .ds li*more-args \" empty
.LB \\n[li*text-indent]u 0 \\n[li*pad-amount] 0 "\\$1" \\*[li*more-args]
.rr li*text-indent
.rr li*pad-amount
.rm li*more-args
..
.\" ####### module tbl #######################################
.\" This module is copied from groff_ms and modified for mm.
.\" Yes, it does not resemble the original anymore :-).
.\" Don't know if I missed something important.
.\" Groff_ms is written by James Clark.
.nr tbl*have-header 0
.nr tbl*header-written 0
.de TS
\\*[debug@dump-args]\\
.br
.if ''\\n[.z]' .SP
.if '\\$1'H' .debug@di tbl*header-div
..
.de tbl@top-hook
.if \\n[tbl*have-header] \{\
.	ie \\n[.t]-\\n[tbl*header-ht]-1v .tbl@print-header
.	el .sp \\n[.t]u
.\}
..
.de tbl@bottom-hook
.if \\n[tbl*have-header] \{\
.	nr T. 1
.\" draw bottom and side lines of boxed tables.
.	T#
.\}
.nr tbl*header-written 0
..
.de tbl@print-header
.ev tbl*ev
'nf
.debug@emit tbl*header-div
.ev
.mk #T
.nr tbl*header-written 1
..
.de TH
\\*[debug@dump-args]\\
.ie '\\n[.z]'tbl*header-div' \{\
.	nr T. 0
.	T#
.	br
.	debug@di
.	nr tbl*header-ht \\n[dn]
.	ne \\n[dn]u+1v
.	nr tbl*have-header 1
.	ie '\\$1'N' .if !\\n[tbl*header-written] .tbl@print-header
.	el .tbl@print-header
.\}
.el .@error \\$0: .TH without .TS H"
..
.de TE
\\*[debug@dump-args]\\
.ie '\\n[.z]'tbl*header-div' .@error \\$0: .TS H but no .TH before .TE
.el \{\
.	nr tbl*have-header 0
.\}
.\" reset tabs
.TAB
..
.de T&
\\*[debug@dump-args]\\
..
.\" ####### module pic #######################################
.de PS
\\*[debug@dump-args]\\
.if !\\n[.$]=2 \{\
.	ds pic*msg \\$0: expected 2 arguments, got \\n[.$]\"
.	as pic*msg ; not preprocessed with pic?\"
.	@error \\*[pic*msg]
.\}
.br
.SP .5
.if r ds*format .if !\\n[ds*lvl] .ne (u;\\$1)+1v
.HTML-IMAGE
..
.de PY
\\*[debug@dump-args]\\
.@reset
.HTML-IMAGE-END
..
.de PE
\\*[debug@dump-args]\\
.PY
.SP .5
..
.\" ####### module eq #######################################
.\"
.nr eq*number 0 1
.ds eq*label
.de EQ
\\*[debug@dump-args]\\
.ds eq*label "\\$1
..
.de eq@check
.if !'\\*[eq*label]'' \{\
.	mk
.	\" space down to middle of equation
'	sp (u;(\\$1-1v)/2)
.	ie \\n[Eq]%2 \{\
.		\"	label to the left
\h'|0'\\*[eq*label]
.	\}
.	el \{\
.		\"	label to the right, possibly compensating for
.		\"	indented display
.		ie \\n[ds*format]=1 \
\h'|\\n[.l]u-\w'\\*[eq*label]'u+\\n[Si]n'\\*[eq*label]
.		el \h'|\\n[.l]u-\w'\\*[eq*label]'u'\\*[eq*label]
.	\}
.	rt
.\}
.ds eq*label
..
.de EN
\\*[debug@dump-args]\\
..
.\"########### module toc ###################
.\" table of contents
.nr toc*slevel 1
.nr toc*spacing \n[Lsp]u
.nr toc*tlevel 2
.nr toc*tab 0
.\"-----------
.\" Table of contents with friends (module lix)
.de TC
\\*[debug@dump-args]\\
.br
.\" print any pending displays and references
.df@print-float 3
.if \\n[ref*was-RS-used] .RP 0 1
.\"
.if \w@\\$1@>0 .nr toc*slevel \\$1
.if \w@\\$2@>0 .nr toc*spacing (u;\\$2*\\n[Lsp])
.if \w@\\$3@>0 .nr toc*tlevel \\$3
.if \w@\\$4@>0 .nr toc*tab \\$4
.if \\n[pg*cols-per-page]>1 .1C
.ds H1txt \\*[Captc]
.ds Tcstatus co
.pg@clear-hd
.EF ""
.OF ""
.pg@next-page
.\"-------------
.if d Ci .toc@read-Ci \\*[Ci]
.nf
.in 0
.ie \\n[Oc] .hd@set-page 1
.el \{\
.	nr toc*pn 1 1
.	af toc*pn i
.	aln ;g toc*pn
.	PF "''\\\\\\\\n[toc*pn]''"
.	am pg@header
.		nr toc*pn +1
\\..
.\}
.nr toc*i 4 1
.while \\n+[toc*i]<10 \{\
.	if !'\\$\\n[toc*i]'' \{\
.		ce
\\$\\n[toc*i]
.		br
.	\}
.\}
.if \\n[.$]<=4 .if d TX .TX
.ie d TY .if \\n[.$]<=4 .TY
.el \{\
.	ce
\\*[Captc]
.	br
.	SP 3
.\}
.if d toc*list .toc*list
.br
.\" print LIST OF XXX
.if d lix*dsfg .lix@print-ds fg FG "\\*[Lf]" \\n[.$]
.if d lix*dstb .lix@print-ds tb TB "\\*[Lt]" \\n[.$]
.if d lix*dsec .lix@print-ds ec EC "\\*[Le]" \\n[.$]
.if d lix*dsex .lix@print-ds ex EX "\\*[Lx]" \\n[.$]
..
.\"-----------
.\" .toc@read-Ci lev1 lev2 lev3 lev4 ... lev7
.de toc@read-Ci
.nr toc*i 0 1
.while \\n+[toc*i]<15 \{\
.	nr toc*hl!\\n[toc*i] \\$[\\n[toc*i]]
.\}
..
.\"-----------
.de toc@entry
.ie \\n[Sectp] \{\
.	toc@save \\$1 "\\*[hd*mark]" "\\$2" \\*[hd*sect-pg]
.\}
.el .toc@save \\$1 "\\*[hd*mark]" "\\$2" \\n[P]
..
.als )E toc@entry
.\"-----------
.de toc@save
.\" collect maxsize of mark if string Ci don't exist.
.if !d Ci \{\
.	if !r toc*hl!\\$1 .nr toc*hl!\\$1 0
.	if \\n[toc*hl!\\$1]<=\w@\\$2@ \{\
.		nr toc*hl!\\$1 \w@\\$2@u
.	\}
.\}
.am toc*list
.\" .toc@set level headernumber text pagenumber
.toc@set \\$1 "\\$2" "\\$3" \\$4
\\..
..
.\"-----------
.\" level mark text pagenumber
.de toc@set
.if \\$1<=\\n[toc*slevel] .SP \\n[toc*spacing]u
.na
.fi
.nr toc*ind 0
.nr toc*i 0 1
.ie d Ci \{\
.	nr toc*ind +\\n[toc*hl!\\$1]u
.\}
.el \{\
.	while \\n+[toc*i]<\\$1 \{\
.		nr toc*ind +\\n[toc*hl!\\n[toc*i]]u
.	\}
.\}
.nr toc*text \\n[toc*ind]u+\\n[toc*hl!\\$1]u
.in \\n[toc*text]u
.ti -\\n[toc*hl!\\$1]u
.\"
.\" length of headernumber space
.nr toc*i \\n[toc*hl!\\$1]-\w@\\$2@
.\"
.ll \\n[@ll]u-\w@\\$4@u-2m
.ne 2v
.\" ragged right ---------------------------------
.ie \\$1>\\n[toc*tlevel] \{\
\\$2
.	sp -1
\\$3\ \ \ \\$4
.	br
.\}
.el \{\
.	\" unnumbered heading --------------------
.	ie '\\$2'' \{\
.		in \\n[toc*ind]u
\\$3\h'1m'
.	\}
.	\" normal heading ------------------------
.	el \{\
\\$2
.		sp -1
\\$3\h'1m'
.	\}
.	ll \\n[@ll]u
.	sp -1
.	nr toc*sep (u;\\n[.l]-\\n[.n]-\\n[.i]-\w@\\$4@)-1m
\h'|\\n[.n]u'\l'\\n[toc*sep]u.'\h'1m'\\$4
.\}
.ll \\n[@ll]u
..
.\"########################### module lix ############################
.\" LIST OF figures, tables, exhibits and equations
.nr lix*fg-nr 0 1
.nr lix*tb-nr 0 1
.nr lix*ec-nr 0 1
.nr lix*ex-nr 0 1
.aln Fg lix*fg-nr
.aln Tb lix*tb-nr
.aln Ec lix*ec-nr
.aln Ex lix*ex-nr
.\"------------
.de FG
\\*[debug@dump-args]\\
.lix@print-line fg Lf \\n+[lix*fg-nr] "\\$1" "\\$2" "\\$3" "\\$4"
..
.de TB
\\*[debug@dump-args]\\
.lix@print-line tb Lt \\n+[lix*tb-nr] "\\$1" "\\$2" "\\$3" "\\$4"
..
.de EC
\\*[debug@dump-args]\\
.lix@print-line ec Le \\n+[lix*ec-nr] "\\$1" "\\$2" "\\$3" "\\$4"
..
.de EX
\\*[debug@dump-args]\\
.lix@print-line ex Lx \\n+[lix*ex-nr] "\\$1" "\\$2" "\\$3" "\\$4"
..
.\"------------
.\" print line with 'figure' in the text
.\" type stringvar number text override flag refname
.de lix@print-line
.ds lix*text "\\$4
.\"
.ie \\n[Sectf] .ds lix*numb \\n[H1]-\\$3
.el            .ds lix*numb \\$3
.\"
.ie !\\n[Of] .ds lix*ds-form .\ \ \"
.el          .ds lix*ds-form "\ \[em]\ \"
.nr lix*in \\n[.i]
.ds lix*label \\*[Cap\\$1]\ \\*[lix*numb]\\*[lix*ds-form]
.if \\n[D]>=2 .tm \\*[Cap\\$1] "\\$4"
.if \\n[D]>=6 .tm \\$0: lix*label="\\*[lix*label]"
.if !'\\$5'' \{\
.	if !0\\$6 .ds lix*label \\*[Cap\\$1]\ \\$5\\*[lix*numb]\\*[lix*ds-form]
.	if 0\\$6=1 .ds lix*label \\*[Cap\\$1]\ \\*[lix*numb]\\$5\\*[lix*ds-form]
.	if 0\\$6=2 .ds lix*label \\*[Cap\\$1]\ \\$5\\*[lix*ds-form]
.\}
.\" print line if not between DS/DE
.ie (\\n[ds*lvl]<1)&(\\n[df*float]=0) \{\
.	lix@print-text "\\*[lix*label]" "\\*[lix*text]" \\$1 \\$2 \\$7
.\}
.el \{\
.	lix@embedded-text "\\*[lix*label]" "\\*[lix*text]" \\$1 \\$2 \\$7
.\}
.\"
..
.\"-----------
.\" label text type stringvar refname
.de lix@print-text
.ie \\n[Sectp] .ds lix*pgnr \\*[hd*sect-pg]
.el            .ds lix*pgnr \\n[%]
.SP \\n[Lsp]u
.misc@ev-keep lix
.@reset
.br
.ie (\w@\\$1\\$2@)>(\\n[.l]-\\n[.i]) \{\
.	in +\w@\\$1@u
.	ti 0
.\}
.el .ce 1
\f3\\$1\fP\\$2
.br
.ev
.\" save line for LIST OF XXX, wth is the width of the label
.if !r lix*wth\\$3 .nr lix*wth\\$3 0
.\" find the maximum width
.if \w@\\*[lix*label]@>\\n[lix*wth\\$3] .nr lix*wth\\$3 \w@\\*[lix*label]@
.if \\n[\\$4] .lix@ds-save \\$3 \\*[lix*pgnr] "\\*[lix*text]" "\\*[lix*label]"
.\" save reference to the figure
.if !'\\$5'' .SETR \\$5 \\*[lix*numb]
..
.\" hide printout until diversion is evaluated
.de lix@embedded-text
\!.ie \\\\n[Sectp] .ds lix*pgnr \\\\*[hd*sect-pg]
\!.el .ds lix*pgnr \\\\n[%]
\!.SP \\\\n[Lsp]u
\!.misc@ev-keep lix
\!.ll \\n[.l]u
\!.@reset
\!.fi
\!.ie (\w@\\$1\\$2@)>(\\\\n[.l]-\\\\n[.i]) \{\
.	in +\w@\\$1@u
\!.	ti 0
\!\f3\\$1\fP\\$2
\!.\}
\!.el \{\
.	ce 1
\!\f3\\$1\fP\\$2
\!.\}
\!.br
\!.ev
.\" save line for LIST OF XXX, wth is the width of the label
\!.if !r lix*wth\\$3 .nr lix*wth\\$3 0
.\" find the maximum width
\!.if \w@\\*[lix*label]@>\\\\n[lix*wth\\$3] .nr lix*wth\\$3 \w@\\*[lix*label]@
\!.if \\\\n[\\$4] .lix@ds-save \\$3 \\\\*[lix*pgnr] "\\*[lix*text]" "\\*[lix*label]"
.\" save reference to the figure
\!.if !'\\$5'' .SETR \\$5 \\*[lix*numb]
..
.\"------------
.\" print complete list of XXXX
.de lix@print-ds
.\" arg: fg,tb,ec,ex text
.ds H1txt \\$3
.ds Tcstatus \\$1
.if !\\n[Cp] .pg@next-page
.in 0
.\" print LIST OF XXXX
.\" execute user-defined macros
.if \\$4<=4 .if d TX\\$2 .TX\\$2
.ie d TY\\$2 .if \\$4<=4 .TY\\$2
.el \{\
.	ce
\\$3
.	SP 3
.\}
.in \\n[lix*wth\\$1]u
.fi
.lix*ds\\$1
..
.\"------------
.\" save line of list in macro
.de lix@ds-save
.\" type pagenumber text
.am lix*ds\\$1
.lix@dsln \\$1 \\$2 "\\$3" "\\$4" \\$5
\\..
..
.\"------------
.\" print appended macro
.\" lix@dsln type pagenumber text headernumber
.de lix@dsln
.nr lix*i \\n[lix*wth\\$1]-\w@\\$4@
.ne 4v
.ll \\n[@ll]u-\w@\\$4@u-\w@\\$2@u-2m
.ti -\\n[lix*wth\\$1]u
\\$4
.sp -1
\\$3\h'1m'
.sp -1
.ll
.nr lix*sep (u;\\n[.l]-\\n[.n]-\\n[.i]-\w@\\$2@)-1m
\h'|\\n[.n]u'\l'\\n[lix*sep]u.'\h'1m'\\$2
.SP \\n[toc*spacing]u
..
.\"########################### module fnt ############################
.\" some font macros.
.\"-----------
.de fnt@switch
.ul 0
.ds fnt*tmp
.nr fnt*prev \\n[.f]
.nr fnt*i 2 1
.while \\n+[fnt*i]<=\\n[.$] \{\
.	if \\n[fnt*i]>3 .as fnt*tmp \,
.	ie (\\n[fnt*i]%2)=1 .as fnt*tmp \\$1\\$[\\n[fnt*i]]
.	el .as fnt*tmp \\$2\\$[\\n[fnt*i]]
.	if \\n[fnt*i]<\\n[.$] .as fnt*tmp \/
.\}
\&\\*[fnt*tmp]\f[\\n[fnt*prev]]
..
.\"-----------
.de B
\\*[debug@dump-args]\\
.ie \\n[.$] .fnt@switch \f3 \f[\\n[.f]] \\$@
.el         .ft 3
..
.de I
\\*[debug@dump-args]\\
.ie \\n[.$] .fnt@switch \f2 \f[\\n[.f]] \\$@
.el         .ft 2
..
.de R
\\*[debug@dump-args]\\
.ie \\n[.$] .fnt@switch \f1 \f[\\n[.f]] \\$@
.el         .ft 1
..
.de IB
\\*[debug@dump-args]\\
.if \\n[.$] .fnt@switch \f2 \f3 \\$@
..
.de BI
\\*[debug@dump-args]\\
.if \\n[.$] .fnt@switch \f3 \f2 \\$@
..
.de IR
\\*[debug@dump-args]\\
.if \\n[.$] .fnt@switch \f2 \f1 \\$@
..
.de RI
\\*[debug@dump-args]\\
.if \\n[.$] .fnt@switch \f1 \f2 \\$@
..
.de RB
\\*[debug@dump-args]\\
.if \\n[.$] .fnt@switch \f1 \f3 \\$@
..
.de BR
\\*[debug@dump-args]\\
.if \\n[.$] .fnt@switch \f3 \f1 \\$@
..
.\"########################### module box ############################
.\" draw a box around some text. Text will be kept on the same page.
.\"
.nr box*ll 0
.\" .B1 and .B2 works like .DS
.de B1
\\*[debug@dump-args]\\
.br
.if \\n[box*ll] .@error \\$0: cannot nest; missing B2?
.nr box*ll \\n[.l]
.nr box*ind \\n[.i]
.nr box*hyp \\n[.hy]
.nr box*wid \\n[.l]-\\n[.i]
.\"
.\" jump to new environment.
.ev box*ev
.debug@di box*div
.ps \\n[@ps]u
.vs \\n[@vs]u
.in 1n
.ll (u;\\n[box*wid]-1n)
.lt (u;\\n[box*wid]-1n)
.@enable-hyphenation
..
.de B2
\\*[debug@dump-args]\\
.br
.if !\\n[box*ll] .@error \\$0: no corresponding B1
.\" In nroff mode, make room for the horizontal rules taking up 1v each.
.if n .sp
.debug@di
.if n .sp
.nr box*height \\n[dn]
.ne \\n[dn]u+1v
.ll \\n[box*ll]u
.in \\n[box*ind]u
.nr box*y-pos \\n[.d]u
.nf
.debug@emit box*div
.fi
\v'-1v+.25m'\
\D'l \\n[box*wid]u 0'\
\D'l 0 -\\n[box*height]u'\
\D'l -\\n[box*wid]u 0'\
\D'l 0 \\n[box*height]u'
.br
.sp -1
.ev
.sp .20v
.in \\n[box*ind]u
.ll \\n[box*ll]u
.rm box*div
.nr box*ll 0
..
.\"########################### module ref ############################
.mso refer-mm.tmac
.nr ref*nr 0 1
.aln Rfnum ref*nr
.aln :R ref*nr		\" for DWB mm compatibility
.nr ref*nr-width 5n
.nr ref*was-RS-used 0	\" for end-of-text
.ds ref*nroff-( [
.ds ref*troff-( \v'-.4m'\s-3
.ds ref*nroff-) ]
.ds ref*troff-) \s0\v'.4m'
.
.de ref*set-mark-style
.nr ref*mark-style \\n[Rfstyle]
.if \\n[Rfstyle]=0 \{\
.	if n .nr ref*mark-style 1
.	if t .nr ref*mark-style 2
.\}
.if \\n[ref*mark-style]=1 \{\
.	ds ref*( \\*[ref*nroff-(]
.	ds ref*) \\*[ref*nroff-)]
.\}
.if \\n[ref*mark-style]=2 \{\
.	ds ref*( \\*[ref*troff-(]
.	ds ref*) \\*[ref*troff-)]
.\}
.if \\n[ref*mark-style]=3 \{\
.	ds ref*( \\*[ref*troff-(]\\*[ref*nroff-(]
.	ds ref*) \\*[ref*nroff-)]\\*[ref*troff-)]
.\}
.rr ref*mark-style
..
.
.ref*set-mark-style
.ds Rf \\*[ref*(]\\n+[ref*nr]\\*[ref*)]
.
.\"
.\" start reference
.\"------------
.de RS
\\*[debug@dump-args]\\
.ref*set-mark-style \" in case the document changed it
.if !''\\$1' .ds \\$1 \\*[ref*(]\\n[ref*nr]\\*[ref*)]
.nr ref*was-RS-used 1
.am ref*mac
.ref@start-print \\n[ref*nr]
\\..
.eo
.am ref*mac RF
..
.\"------------
.\" Argument dumping belated because RS turned the escape character off.
.de RF
.ec
\\*[debug@dump-args]\\
.am ref*mac
.ref@stop-print
\\..
..
.\"------------
.de ref@start-print
.debug@di ref*div
.LB \\*[Rpfmt]
.LI "\\$1."
..
.\"------------
.de ref@stop-print
.LE
.debug@di
.ne \\n[dn]u
.ev ref*ev2
.nf
.debug@emit ref*div
.ev
.rm ref*div
.if \\n[Ls] .SP \\n[Lsp]u
..
.\"-----------
.de RP
\\*[debug@dump-args]\\
.if !d ref*mac \{\
.	@warning \\$0: ignoring; no references defined
.	return
.\}
.\" Wart: mm treats the first argument as Boolean based on its
.\" (non-)emptiness, not a numeric value.
.nr ref*reset-counter 1
.if !''\\$1' \{\
.	ie \B'\\$1' .nr ref*reset-counter \\$1
.	el          .@warning \\$0: treating non-numeric first \
argument '\\$1' as '1'
.\}
.if \\n[ref*reset-counter] .nr ref*nr 0 1
.nr ref*i \\n[Rpej]
.if !''\\$2' \{\
.	ie \B'\\$2' .nr ref*i \\$2
.	el          .@warning \\$0: ignoring non-numeric second \
argument: '\\$2'
.\}
.if \\n[ref*i]<2 .SK
.ref@print-refs
.if (\\n[ref*i]=0):(\\n[ref*i]=2) .SK
.rr ref*reset-counter
..
.\"-----------
.\" called by end-of-text!
.de ref@eot-print
.\".if \\n[ref*was-RS-used] \{\
.if d ref*mac \{\
.	if \\n[D]>=2 .tm References
.	nr ref*was-RS-used 0
.	br
.	misc@ev-keep ne
.	@reset
\c
'	bp
.	ev
.	ref@print-refs
.\}
..
.\"-----------
.\" prints the references
.de ref@print-refs
.toc@save 1 "" "\\*[Rp]" \\n[%]
.ie d RPX \{\
.	if \\n[D]>=5 .tm \\$0: calling user-defined RPX macro
.	RPX
.\}
.el \{\
.	SP 2
.	ce
.	nop \f2\\*[Rp]\fP
.	sp
.\}
.nr ref*ll \\n[.l]
.misc@ev-keep ref*ev
.ll \\n[ref*ll]u
.in 0
.ref*mac
.in
.rm ref*mac
.ev
.nr ref*was-RS-used 0
..
.\"########################### module app ############################
.\"
.nr app*nr 0 1
.af app*nr A
.nr app*dnr 0 1
.nr app*flag 0
.\"------------
.\" .APP name text
.\" name == "" -> autonumber
.de APP
\\*[debug@dump-args]\\
.\" .if \\n[.$]<2 .@error "APP: too few arguments"
.app@set-ind "\\$1"
.\"
.ds Tcstatus ap
.ds Apptxt \\$2
.\"
.ie \\n[Aph] .app@header \\*[app*ind] "\\$2"
.el          .bp
.app@index "\\*[app*ind]" "\\$2"
..
.\"------------
.\" .APPSK name pages text
.\" name == "" -> autonumber
.de APPSK
\\*[debug@dump-args]\\
.if \\n[.$]<2 .@error \\$0: expected 2 or 3 arguments, got \\n[.$]
.app@set-ind "\\$1"
.\"
.ds Tcstatus ap
.ds Apptxt \\$3
.\"
.ie \\n[Aph] .app@header \\*[app*ind] "\\$3"
.el          .bp
.app@index "\\*[app*ind]" "\\$3"
.pn +\\$2
..
.\"------------
.de app@set-ind
.ie \w@\\$1@ .ds app*ind \\$1
.el \{\
.	if !\\n[app*flag] \{\
.		nr H1 0 1
.		af H1 A
.		af H1h A
.		nr app*flag 1
.	\}
.	ds app*ind \\n+[app*nr]
.	nr H1 \\n+[app*dnr]
.	nr H1h \\n[app*dnr]
.\}
.\"	clear lower counters
.nr app*i 1 1
.while \\n+[app*i]<15 .nr H\\n[app*i] 0 1
..
.\"------------
.de app@index
.toc@save 1 "" "\\*[App] \\$1: \\$2" \\n[%]
..
.\"------------
.\" app@header name text
.de app@header
.bp
.SP (u;\\n[Lsp]*4)
.ce 1
\s+4\f3\\*[App]\ \\$1\fP\s0
.SP (u;\\n[Lsp]*2)
.if \w@\\$2@<\\n[.l] .ce 1
\f3\s+2\\$2\s0\fP
.SP (u;\\n[Lsp]*4)
..
.als APPX app@header
.\"########################### module cov ############################
.\" title stored in diversion cov*title
.\" abstract stored in diversion cov*abstract
.\"	placement value to `AS` stored in cov*abstract-placement
.\"	indentation argument to `AS` stored in cov*abstract-indent
.\" number of authors stored in cov*au
.\" author(s) stored in cov*au!x!y
.\" number of authors' titles stored in cov*at!x
.\" title(s) of author(s) stored in cov*at!x!y
.\" 	x is the author-index [1-cov*au], y is the argument-index [1-9].
.\" author(s) firm stored in cov*firm
.\" date (if .ND was called) is stored in cov*date
.\"
.\"
.nr cov*au 0
.de TL
\\*[debug@dump-args]\\
.ds @cover \\$0
.@disable IA IE WA WE LO LT \" can't use with LT and friends
.if \\n[.$]>0 .ds cov*title-charge-case \\$1
.if \\n[.$]>1 .ds cov*title-file-case \\$2
.pg@disable-top-trap
.eo
.de cov*title AU
..
.\"-------------------
.de cov@title-end
.ec
..
.\"-------------------
.\" .AU [name [initials [loc [dept [ext [room [arg [arg [arg]]]]]]]]]
.\" Argument dumping belated because TL turned the escape character off.
.de AU
.cov@title-end
\\*[debug@dump-args]\\
.if !\\n[.$] .return \" AU is being used only to end a TL.
.pg@disable-top-trap
.nr cov*au +1
.nr cov*at!\\n[cov*au] 0 \" no titles for this author yet
.nr cov*i 0 1
.ds cov*au!\\n[cov*au]!1
.while \\n[.$]>=\\n+[cov*i] \{\
.	ds cov*au!\\n[cov*au]!\\n[cov*i] "\\$[\\n[cov*i]]
.\}
.if (\\n[.$]>=3)&(\w@\\$3@) \{\
.	if d cov*location-\\$3] \{\
.		ds cov*au!3!\\n[cov*au] \\*[cov*location-\\$3]
.	\}
.\}
..
.\"-------------------
.\" .AT title [...]
.\" Any quantity of titles may be declared.
.\" Must be called directly after the corresponding .AU.
.de AT
\\*[debug@dump-args]\\
.if !\\n[.$] \{\
.	@warning \\$0: ignoring; no arguments specified
.	return
.\}
.nr cov*at!\\n[cov*au] \\n[.$]
.nr cov*i 0 1
.while \\n[.$]>=\\n+[cov*i] \{\
.	ds cov*at!\\n[cov*au]!\\n[cov*i] "\\$[\\n[cov*i]]
.\}
..
.\"-------------------
.de AF
\\*[debug@dump-args]\\
.if !''\\$1' .ds cov*firm \\$1
..
.\" TODO: Kill this off in groff 1.24.0 release + 2 years.
.de AST
\\*[debug@dump-args]\\
.@warning \\$0: macro is deprecated; define string 'Abstract' instead
.ds Abstract "\\$1\"
..
.de AS
\\*[debug@dump-args]\\
.pg@disable-top-trap
.if d cov*abstract .@error \\$0: only one abstract allowed
.if !''\\n[.z]' .@error \\$0: no diversion allowed (previous .AS?)
.nr cov*abstract-placement 0\\$1
.nr cov*abstract-indent (n;0\\$2)
.de cov*abstract AE
..
.de AE
\\*[debug@dump-args]\\
..
.\" XXX: In principle, a localization file can (and should be able to)
.\" customize the month's register format, but we look up the string for
.\" the month name assuming that `mo`'s format will be '0'.  To date,
.\" however, no one has submitted a localization file for groff that
.\" uses an alternative register format for `mo` (or `dy`).  If that day
.\" comes, we might rename MO1 to MO01 (and so on) and look up the
.\" string with a dedicated register using a format of '00'.
.ds cov*local-date-format \E*[MO\En[mo]] \En[dy], \En[year]
.af cov*iso-mm 00
.af cov*iso-dd 00
.ds cov*iso-date-format   \En[year]-\En[cov*iso-mm]-\En[cov*iso-dd]
.\" TODO: After `ISODATE` is removed for groff 1.25, this macro can stop
.\" handling an argument, instead testing the `Isodate` register.
.de cov*set-date
.\" In case the document has changed `mo` or `dy`, make sure their
.\" alternatives using ISO 8601 format are synchronized.
.nr cov*iso-mm \\n[mo]
.nr cov*iso-dd \\n[dy]
.ie '0'\\$1' .ds cov*date \\*[cov*local-date-format]
.el          .ds cov*date \\*[cov*iso-date-format]
..
.de ISODATE
\\*[debug@dump-args]\\
.@warning \\$0: macro is deprecated; define register 'Isodate' instead
.cov*set-date \\$@
..
.de ND
\\*[debug@dump-args]\\
.ie \\n[.$] .ds cov*date "\\$1\"
.el         .cov*set-date \\n[Isodate]
..
.ND
.als DT cov*date
.\"-------------------
.\" Save technical memorandum numbers.
.de TM
\\*[debug@dump-args]\\
.if !\\n[.$] \{\
.	@warning \\$0: ignoring; no arguments specified
.	return
.\}
.nr cov*i 0 1
.while \\n[.$]>=\\n+[cov*i] .ds cov*mt-tm!\\n[cov*i] \\$[\\n[cov*i]]
.nr cov*mt-tm-max \\n[.$]
..
.\"-----------------------
.\" cover sheet
.\" the file must have the following last lines (somewhere):
.\" .pg@enable-top-trap
.\" .bp 1
.\" .pg@enable-trap
.ds cov*mt-file!0 0.MT
.ds cov*mt-file!1 0.MT
.ds cov*mt-file!2 0.MT
.ds cov*mt-file!3 0.MT
.ds cov*mt-file!4 4.MT
.ds cov*mt-file!5 5.MT
.ds cov*mt-file!6 0.MT
.\"------------
.de MT
\\*[debug@dump-args]\\
.ds @cover \\$0
.@disable COVER IA IE WA WE LO LT
.ie \\n[.$] \{\
.	ie d cov*mt-file!\\$1 .ds cov*mt-type \\$1
.	el .ds cov*mt-type 6
.\}
.el .ds cov*mt-type 1
.ds cov*mt-addressee "\\$2
.ds cov*mt-type-text "\\$1
.ie d @country .ds cov*str mm/\\*[@country]_
.el            .ds cov*str mm/
.mso \\*[cov*str]\\*[cov*mt-file!\\*[cov*mt-type]]
..
.de COVER
\\*[debug@dump-args]\\
.ds @cover \\$0
.@disable IA IE WA WE LO LT MT
.ie !\\n[.$] .ds cov*cov-type ms
.el          .ds cov*cov-type \\$1
.pg@disable-top-trap
.ie d @country .ds cov*str mm/\\*[@country]_\\*[cov*cov-type].cov
.el            .ds cov*str mm/\\*[cov*cov-type].cov
.mso \\*[cov*str]
..
.\"########################### module qrf ############################
.\" forward and backward reference thru special files.
.\"
.\" check if stderr-method is wanted
.\" This was needed when I discovered that groff was considered unsafe
.\" and groff -U didn't work. It's a workaround like the original
.\" index method, but not in my view elegant enough.
.
.\" Store name of the interface macro calling qrf*validate-identifier.
.\" Re-empty it after use to catch internal logic errors.
.ds qrf*caller \" empty
.
.\" Validate argument as roff identifier.
.\" qrf*validate-identifier candidate
.de qrf*validate-identifier
.if !\\n[.$]=1 .@abort expected an argument, got \\n[.$]
.if '\\*[qrf*caller]'' .@abort qrf*caller string not initialized
.if !\A'\\$1' \{
.	ds qref*msg \\*[qrf*caller]: '\\$1' is not a valid string\"
.	as qref*msg " identifier\"
.	@error \\*[qref*msg]
.\}
.ds qrf*caller \" empty
..
.\"
.\" INITR id
.\" Initialize reference system.  Read/write file id.qrf.
.de INITR
\\*[debug@dump-args]\\
.if \\n[.$]<1 .@error \\$0: expected an argument
.ds qrf*file \\$1.qrf
.nr qrf*pass 2 \" magic number
.if \\n[D]>=6 .tm \\$0: source \\*[qrf*file]
.ie \\n[Ref] \{\
.	tm .\\\\" Rfilename: \\*[qrf*file]
.\}
.el .so \\*[qrf*file]
..
.\"---------------
.\" SETR ref-name [string]
.\" Set (define) a reference ref-name; store auxiliary datum in string.
.de SETR
\\*[debug@dump-args]\\
.if \\n[.$]<1 .@error \\$0: expected 1 or 2 arguments, got \\n[.$]
.if !r qrf*pass .@error \\$0: references uninitialized; call INITR first
.ds qrf*caller \\$0\"
.if \\n[Ref] \{\
.	qrf*validate-identifier \\$1
.	ds qrf*name qrf*ref-\\$1
.	if \\n[D]>=6 \
.		tm \\$0: ref \\*[qrf*name]=\\*[hd@mark-trimmed],\\n[%]
.	\" heading-number
.	ds \\*[qrf*name]-hn \\*[hd@mark-trimmed]
.	\" page-number
.	ds \\*[qrf*name]-pn \\n[%]
.	\"
.	if \\n[Ref] \{\
.		tm .ds \\*[qrf*name]-hn \\*[hd@mark-trimmed]
.		tm .ds \\*[qrf*name]-pn \\n[%]
.		if \\n[.$]>1 \{\
.			qrf*validate-identifier \\$2
.			tm .ds \\*[qrf*name]-xx \\$2
.		\}
.	\}
.\}
..
.\"---------------
.\" Interpolate or retrieve reference ref-name's auxiliary datum.
.\" GETST ref-name [string]
.de GETST
\\*[debug@dump-args]\\
.if \\n[.$]<1 .@error \\$0: expected 1 or 2 arguments, got \\n[.$]
.if !r qrf*pass .@error \\$0: references uninitialized; call INITR first
.ds qrf*caller \\$0\"
.qrf*validate-identifier \\$1
.ds qrf*name qrf*ref-\\$1
.if d \\*[qrf*name]-xx \{\
.	ie \\n[.$]>1 \{\
.		ds qrf*caller \\$0\"
.		qrf*validate-identifier \\$2
.		ds \\$2 \\*[\\*[qrf*name]-xx]
.	\}
.	el \\*[\\*[qrf*name]-xx]\c
.\}
..
.\"---------------
.\" Interpolate or retrieve reference ref-name's heading number.
.\" GETHN ref-name [string]
.de GETHN
\\*[debug@dump-args]\\
.if \\n[.$]<1 .@error \\$0: expected 1 or 2 arguments, got \\n[.$]
.if !r qrf*pass .@error \\$0: references uninitialized; call INITR first
.ds qrf*caller \\$0\"
.qrf*validate-identifier \\$1
.ds qrf*name qrf*ref-\\$1
.if d \\*[qrf*name]-hn \{\
.	ie \\n[.$]>1 \{\
.		ds qrf*caller \\$0\"
.		qrf*validate-identifier \\$2
.		ds \\$2 \\*[\\*[qrf*name]-hn]
.	\}
.	el \\*[\\*[qrf*name]-hn]\c
.\}
..
.\"---------------
.\" Interpolate or retrieve reference ref-name's page number.
.\" GETPN ref-name [string]
.de GETPN
\\*[debug@dump-args]\\
.if \\n[.$]<1 .@error \\$0: expected 1 or 2 arguments, got \\n[.$]
.if !r qrf*pass .@error \\$0: references uninitialized; call INITR first
.ds qrf*caller \\$0\"
.qrf*validate-identifier \\$1
.ds qrf*name qrf*ref-\\$1
.if d \\*[qrf*name]-pn \{\
.	ie \\n[.$]>1 \{\
.		ds qrf*caller \\$0\"
.		qrf*validate-identifier \\$2
.		ds \\$2 \\*[\\*[qrf*name]-pn]
.	\}
.	el \\*[\\*[qrf*name]-pn]\c
.\}
..
.\"----------
.\" Retrieve and interpolate reference ref-name's heading and page data.
.\" GETR ref-name
.de GETR
\\*[debug@dump-args]\\
.if \\n[.$]<1 .@error \\$0: expected an argument
.if !r qrf*pass .@error \\$0: references uninitialized; call INITR first
.ds qrf*caller \\$0\"
.qrf*validate-identifier \\$1
.GETHN \\$1 Qrfh
.GETPN \\$1 Qrfp
\\*[Qrf]
..
.\"########################### module ind ############################
.\"--------------------
.\" initialize index
.\" INITI type filename [macro]
.\" XXX: Since we can build only one index at a time[1], it shouldn't be
.\" necessary to have a mandatory filename argument[2].  Consider
.\" letting the mmroff Perl script generate a temporary filename for us.
.\"
.\" [1] Why?  Indexes go through Perl anyway, and it can keep track of
.\" an arbitrary number of lists to sort independently.
.\"
.\" [2] Just "name" would be a better term for it since we
.\" unconditionally suffix it with ".ind".
.de INITI
\\*[debug@dump-args]\\
.if \\n[.$]<2 .@error \\$0: expected 2 or 3 arguments, got \\n[.$]
.ds ind*ref \" empty
.ds ind*type \\$1
.nr ind*type-is-valid 0
.if '\\*[ind*type]'N' .nr ind*type-is-valid 1
.if '\\*[ind*type]'H' .nr ind*type-is-valid 1
.if '\\*[ind*type]'B' .nr ind*type-is-valid 1
.if !\\n[ind*type-is-valid] .@error \\$0: invalid index type '\\$1'
.rr ind*type-is-valid
.if \\n[D]>=6 .tm INITI: type=\\*[ind*type]
.if '\\$2'' .@error \\$0: index file name not specified
.if d ind*file .@error \\$0: index file name already set
.ds ind*file \\$2.ind
.if \\n[D]>=6 .tm INITI: source \\*[ind*file]
.if \\n[Ref] \{\
.	if \\n[.$]>2 .tm .\\\\" Imacro: \\$3
.\}
..
.\"---------------
.\" collect index entry
.\" IND term ...
.de IND
\\*[debug@dump-args]\\
.if !d ind*file .@error \\$0: no active index; call INITI first
.if \\n[.$]<1 .@error \\$0: expected an argument
.if '\\$1'' .@error \\$0: cannot record empty index entry
.if \\n[nl]<0 .@error \\$0: cannot record index entry when not on a page
.ds ind*line \\$1
.while \\n[.$]>0 \{\
.	shift
.	as ind*line \t\\$1
.\}
.if '\\*[ind*type]'N' .ds ind*ref \\n[%]
.if '\\*[ind*type]'H' .ds ind*ref \\*[hd@mark-trimmed]
.if '\\*[ind*type]'B' .ds ind*ref \\*[hd@mark-trimmed]\t\\n[%]
.as ind*line \\*[ind*ref]
.if \\n[Ref] .tm .\\\\" IND \\*[ind*line]
..
.\" print index
.de INDP
\\*[debug@dump-args]\\
.ie \\n[Ref] .tm .\\\\" Index: \\*[ind*file]
.el \{\
.	if !\\n[Cp] .pg@next-page
.	\" print INDEX
.	\" execute user-defined macros
.	ie d TXIND .TXIND
.	el .SK
.	ie d TYIND .TYIND
.	el \{\
.		ce
\\*[Index]
.		SP 3
.		2C
.		nf
.	\}
'	so  \\*[ind*file]
.	ie d TZIND .TZIND
.	el \{\
.		fi
.		1C
.	\}
.\}
.rm ind*file
..
.\"########################### module let ############################
.\" Letter macros
.\"------------------------
.\" Formal closing
.de FC
\\*[debug@dump-args]\\
.df@print-float 3
.ie \\n[.$] .ds let*i \\$1
.el         .ds let*i \\*[Letfc]
.ie d let*type .let@fc_\\*[let*type] "\\*[let*i]" \\$@
.el            .let@formal-closing "\\*[let*i]" \\$@
..
.\"-------
.de let@formal-closing
.ne 5v
.in (u;\\n[.l]/2)
.sp
\\$1
.in
..
.\"------------------------
.\" Signature line
.nr let*sg-suppress-all 0
.nr let*sg-suppress-annotation 0
.de SG
\\*[debug@dump-args]\\
.if \\n[let*sg-suppress-all] .return
.ie d let*type .let*lt-sign \\$@
.el            .let*mt-sign \\$@
..
.\"------------------------
.de let*lt-sign
.\" We hard-code the SG macro name here since this macro is internal but
.\" only SG calls it.
.if !d let@sg_\\*[let*type] .@error SG: letter type '\\*[let*type]' \
undefined
.df@print-float 3
.nr let*i 0 1
.nr let*j 0
.while \\n+[let*i]<=\\n[let*wa-n] \{\
.if \\n[let*i]=\\n[let*wa-n] .nr let*j 1
.let@sg_\\*[let*type] "\\*[let*wa-name!\\n[let*i]]" "\\*[let*wa-title!\\n[let*i]]" \\n[let*i] \\n[let*j] \\$@
.\}
..
.\"------------------------
.\" Memorandum signature
.de let*mt-sign
.df@print-float 3
.ne \\n[cov*au]u*4v
.ie \\n[.$]>1 .nr let*k 1
.el           .nr let*k \\n[cov*au]
.ds let*anno \" secretarial annotation
.if d cov*au!\\n[let*k]!3 \{\
.	as let*anno \\*[cov*au!\\n[let*k]!3]\"
.	if d cov*au!\\n[let*k]!4 \
.		as let*anno -\\*[cov*au!\\n[let*k]!4]-\"
.\}
.nr let*i 0 1
.while \\n+[let*i]<=\\n[cov*au] \{\
.	if \\n[let*i]>1 .as let*anno /\"
.	if d cov*au!\\n[let*i]!2 \{\
.		as let*anno \\*[cov*au!\\n[let*i]!2]\"
.	\}
.\}
.if !''\\$1' .as let*anno -\\$1
.in (u;\\n[.l]/2)
.nf
.ft \*[@metadata-font]
.nr let*i 0 1
.while \\n+[let*i]<=\\n[cov*au] \{\
.	ne 3v+\\n[cov*at!\\n[let*i]]v
.	SP 3v
.	if \\n[let*i]=\\n[let*k] \{\
.		if !\\n[let*sg-suppress-annotation] \{\
.			\" Set annotation to left of last author's name.
.			\" It does _not_ get the metadata font.
.			nop \Z'\h'-(u;\\n[.l]/2)'\f[R]\\*[let*anno]\f[]'\c
.		\}
.	\}
.	nop \\*[cov*au!\\n[let*i]!1]
.	\" Set author's title(s).
.	nr let*j 0 1
.	while \\n+[let*j]<=\\n[cov*at!\\n[let*i]] \{\
.		nop \\*[cov*at!\\n[let*i]!\\n[let*j]]
.	\}
.\}
.ft
.fi
.in
..
.\"------------------------
.\" Approval signature
.nr let*name-line-length 40n
.nr let*date-line-length 15n
.\" We _don't_ use em dashes instead of low lines in nroff mode here
.\" (see ft@init-footnote).  The low line better approximates a baseline
.\" rule to indicate where a human should apply a stylus to paper, and
.\" a broken rather than a solid rule is not a defect for this purpose.
.ds let*name-line \l'\n[let*name-line-length]u'
.ds let*date-line \l'\n[let*date-line-length]u'
.nr let*approval-gap 5m
.de AV
\\*[debug@dump-args]\\
.ne 6v
.nf
.sp
.ie \\n[.$]<2 \\*[Letapp]
.el           .sp
.sp 2
.\" Center the `Letdate` label below its line.
.ie \w'\\*[Letdate]'>=\\n[let*date-line-length] .nr let*extra-gap 0
.el .nr let*extra-gap \\n[let*date-line-length]-\w'\\*[Letdate]'/2
.nop \\*[let*name-line]\h'\\n[let*approval-gap]u'\\*[let*date-line]
.nop \Z'\\$1'\h'\\n[let*name-line-length]u'\
\h'\\n[let*approval-gap]u+\\n[let*extra-gap]u'\
\\*[Letdate]
.fi
.rr let*extra-gap
..
.\"------------------------
.\" Letter signature
.de AVL
\\*[debug@dump-args]\\
.ne 6v
.nf
.sp 3
.nop \\*[let*name-line]
.nop \Z'\\$1'
.fi
..
.\"------------------------
.\" Letter type
.\" let@header is called from the header. It is supposed
.\" to remove the alias itself.
.de LT
\\*[debug@dump-args]\\
.ds @cover \\$0
.@disable AF AS AE AT AU COVER CS OK TL MT \" same list as LO
.ds let*type BL
.nr Pi 5
.nr Pt 0
.if !''\\$1' .ds let*type \\$1
.if !d let@head_\\*[let*type] .@error \\$0: unknown letter type '\\$1'
.shift
.als let@header let@head_\\*[let*type]
.let@init_\\*[let*type] \\$@
.if \n[D]>=6 .tm \\$0: let*type="\\*[let*type]"
..
.\"-----------
.\" Blocked letter
.de let@init_BL
..
.de let@head_BL
.rm let@header
.let@print-head 1 1
..
.de let@sg_BL
.ne 5v
.nf
.in (u;\\n[.l]/2)
.sp 3v
\\$1
\\$2
.in
.if \\$4 .sp
.if \w'\\$5'&\\$4 \\$5
.fi
..
.als let@fc_BL let@formal-closing
.\"-----------
.\" Semiblocked letter
.de let@init_SB
.nr Pt 1
..
.de let@head_SB
.rm let@header
.let@print-head 1
..
.als let@sg_SB let@sg_BL
.als let@fc_SB let@formal-closing
.\"-----------
.\" Full-blocked letter
.de let@init_FB
..
.de let@head_FB
.rm let@header
.let@print-head
..
.de let@sg_FB
.ne 5v
.nf
.sp 3v
\\$1
\\$2
.if \\$4 .sp
.if \w'\\$5'&\\$4 \\$5
.fi
..
.de let@fc_FB
.ne 5v
.sp
\\$1
..
.\"-----------
.\" Simplified letter
.de let@init_SP
..
.de let@head_SP
.rm let@header
.let@print-head
..
.de let@sg_SP
.nf
.if \\$3=1 .sp
.sp
.ie '\\$2'' .misc@toupper "\\$1"
.el         .misc@toupper "\\$1, \\$2"
.if \\$4 .sp
.if \w'\\$5'&\\$4 \\$5
.fi
..
.de let@fc_SP
.\" Simplified letters have no formal closing, just space before SG.
.sp 2
..
.\"--------------------------------------
.\" format everything up to the body text of a letter
.\"
.\" let@print-head [want-indent] [want-space-before-date-line]
.de let@print-head
.nf
.sp |11
.if '1'\\$1' .in (u;\\n[.l]/2)
.\" ---- writer's (name and) address
.ie d let@wa-div .debug@emit let@wa-div
.el              .sp 3
.\" ---- date
.if '1'\\$2' .sp
.nop \\*[cov*date]
.sp
.if '1'\\$1' .if !d let*lo-CN .if !d let*lo-RN .sp 2
.\" ---- confidential notation
.if d let*lo-CN \{\
.	ti 0
.	ie !''\\*[let*lo-CN]' \\*[let*lo-CN]
.	el \\*[LetCN]
.	sp
.\}
.\" ---- reference notation
.if d let*lo-RN \{\
\\*[LetRN] \\*[let*lo-RN]
.	sp
.\}
.\" ---- recipient's (name and) address
.sp
.in 0
.nr let*i 0 1
.while \\n+[let*i]<=\\n[let*ia-n] \{\
\\*[let*ia-name!\\n[let*i]]
\\*[let*ia-title!\\n[let*i]]
.\}
.if d let@ia-div .debug@emit let@ia-div
.\" ---- attention notation
.if d let*lo-AT \{\
.	sp
\\*[LetAT] \\*[let*lo-AT]
.\}
.\" ---- salutation
.if !'\\*[let*type]'SP' .if d let*lo-SA \{\
.	sp
.	ti 0
.	ie !''\\*[let*lo-SA]' \\*[let*lo-SA]
.	el \\*[LetSA]
.\}
.\" ---- subject notation
.if d let*lo-SJ \{\
.	ie '\\*[let*type]'SP' \{\
.		sp 2
.		misc@toupper "\\*[let*lo-SJ]"
.	\}
.	el \{\
.		sp
.		if '\\*[let*type]'SB' .ti +5m
\\*[LetSJ] \f[\\*[@metadata-font]]\\*[let*lo-SJ]\fP
.	\}
.	sp
.\}
.sp
.fi
..
.\"-------------------
.\" .IA [name [title]]
.nr let*ia-n 0 1
.de IA
\\*[debug@dump-args]\\
.if \\n[.$] .ds let*ia-name!\\n+[let*ia-n] \\$1
.if \\n[.$]>1 .ds let*ia-title!\\n[let*ia-n] \\$2
.ev let@ev
.@reset
'nf
.debug@di let@ia-div
.eo
..
.de IE
.ec
\\*[debug@dump-args]\\
.debug@di
.ev
..
.\"-------------------
.\" .WA [name [title]]
.nr let*wa-n 0 1
.de WA
\\*[debug@dump-args]\\
.if \\n[.$] .ds let*wa-name!\\n+[let*wa-n] \\$1
.if \\n[.$]>1 .ds let*wa-title!\\n[let*wa-n] \\$2
.ev let@ev
.@reset
'nf
.debug@di let@wa-div
.it \\n[Letwam] let@wa-drain
.eo
..
.\"------
.de let@wa-drain
.it
.debug@di
.debug@di let@wa-junk \" never emitted
..
.\"------
.de WE
.ec
\\*[debug@dump-args]\\
.it
.debug@di
.ev
.if d let@wa-junk .rm let@wa-junk
..
.\"-------------------
.\" Notations ("Copy to", etc.)
.nr let*ns-suppress 0
.de NS
\\*[debug@dump-args]\\
.if \\n[let*ns-suppress] \{\
.	ie \\n[.$] .return
.	el         .debug@box let*ns-discard
.\}
.sp
.ie !''\\$2' .ds let*str \\$1
.el \{\
.	ie \\n[.$]>0 \{\
.		ie !\w'\\$1' .ds let*str \\*[Letns!\\*[Letnsdef]]
.		el \{\
.			ie d Letns!\\$1 .ds let*str \\*[Letns!\\$1]
.			el .ds let*str \\*[Letns!copy](\\$1)\\*[Letns!to]
.		\}
.	\}
.	el .ds let*str \\*[Letns!\\*[Letnsdef]]
.\}
.ne 2
.nf
\\*[let*str]
..
.de NE
\\*[debug@dump-args]\\
.if \\n[let*ns-suppress] \{\
.	debug@box
.	return
.\}
.fi
..
.\"-------------------
.\" Letter options
.de LO
\\*[debug@dump-args]\\
.ds @cover \\$0
.@disable AF AS AE AT AU COVER CS OK TL MT \" same list as LT
.if !\\n[.$] \{\
.	@warning \\$0: ignoring; no arguments specified
.	return
.\}
.if !d Let\\$1 .@error \\$0: unrecognized option '\\$1'
.ds let*lo-\\$1 \\$2
.if \n[D]>=6 .tm \\$0: let*lo-\\$1="\\$2"
..
.\"--------------------
.\" Start with a clean slate
.@reset
.
.\" Local Variables:
.\" mode: nroff
.\" fill-column: 72
.\" End:
.\" vim: set filetype=groff textwidth=72:
