]> git.ipfire.org Git - thirdparty/man-pages.git/commitdiff
scripts/LinuxManBook/: Simplify pipeline
authorAlejandro Colomar <alx@kernel.org>
Thu, 30 Nov 2023 23:55:11 +0000 (00:55 +0100)
committerAlejandro Colomar <alx@kernel.org>
Fri, 1 Dec 2023 13:13:35 +0000 (14:13 +0100)
Call the groff(1) pipeline only once.  This optimizes around 2 seconds,
while also simplifying the code.

This change was originally written by Deri, with some parts written by
Brian.  I took the script that Deri sent, and split it so that the
groff(1) pipeline is called from the shell script, and the Perl script
is limited to editing the man(7) pages.  This helps me understand the
process, since my understanding of Perl is very limited.  It also makes
this change smaller, so that it's less of a big-bang.

Link: <https://lore.kernel.org/linux-man/ZWkO4qPC4BxkwBNm@debian/T/#m3d453440b02dd189bc12d2e629c4026206025b40>
Co-developed-by: Deri James <deri@chuzzlewit.myzen.co.uk>
Co-developed-by: Brian Inglis <Brian.Inglis@Shaw.ca>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
scripts/LinuxManBook/LMBfront.roff [moved from scripts/LinuxManBook/LMBfront.ms with 78% similarity]
scripts/LinuxManBook/anmark.tmac [deleted file]
scripts/LinuxManBook/build.sh
scripts/LinuxManBook/prepare.pl
scripts/LinuxManBook/utp.mac [deleted file]

similarity index 78%
rename from scripts/LinuxManBook/LMBfront.ms
rename to scripts/LinuxManBook/LMBfront.roff
index c034dd58adabf99bda878c2d0b8c9e1ea5f4d7eb..fdf1a98206c92ee624e69922de03205641fdce4b 100644 (file)
@@ -1,6 +1,3 @@
-.ig
-       front.t
-..
 .de Hl
 .br
 \l'\\n[.l]u-\\n[.i]u\&\\$1'
@@ -8,31 +5,29 @@
 ..
 .ps 10
 .vs 12
-.nr PS 10
-.nr VS 12
-.nr SS_prefix 1v
-.nr do-page 0
-.Nh 0 0
-.\" .so utp.mac
-.\" .utp
+.po 2c
+.ll 17c
+.sp 2.5c
 \Z@\D't 8p'@
 .Hl
 \D't 0'
 .sp .6i
-.DS R
+.ad r
 .ps 52
 \m[maroon]GNU/Linux\m[]
 .sp 18p
 .ps 16
 \f[BMB]THE MAN-PAGES BOOK\fP
-.sp 30p
-.sp 1.4i
+.sp 6i
 .ps 12
 \f[HB]Maintainers:\fP
 .sp 2p
 .ps 10
 \f[HB]Alejandro Colomar <alx@kernel.org> 2020 - present (5.09 - HEAD)
+.brp
 Michael Kerrisk <mtk.manpages@gmail.com> 2004 - 2021    (2.00 - 5.13)
+.brp
 Andries Brouwer <aeb@cwi.nl> 1995 - 2004     (1.6  - 1.70)
+.brp
 Rik Faith 1993 - 1995     \0(1.0  - 1.5)\fP
-.DE
+.bp
diff --git a/scripts/LinuxManBook/anmark.tmac b/scripts/LinuxManBook/anmark.tmac
deleted file mode 100644 (file)
index 9bf4e16..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-.nr PDFOUTLINE.FOLDLEVEL 1
-.defcolor pdf:href.colour rgb 0.00 0.25 0.75
-.pdfinfo /Title "The Linux man-pages Book"
-.special S TINOR
index a6e578f6468122e89edaa4939ca2e2c87067c183..8e373c0730d43778b635ad7fa1d01ea29df2a1d1 100755 (executable)
@@ -3,25 +3,13 @@
 # SPDX-License-Identifier: GPL-3.0-or-later
 
 (
-       "$(dirname "$0")"/prepare.pl "$1" \
-       | preconv \
-       | pic \
-       | tbl \
-       | eqn -Tpdf \
-       | troff -Tpdf -dPDF.EXPORT=1 -dLABEL.REFS=1 -dpaper=a4 \
-               -M"$(dirname "$0")" -mandoc -manmark -rC1 -rCHECKSTYLE=3 \
-               2>&1 >/dev/null \
-       | LC_ALL=C grep '^\. *ds ';
-
+       cat "$(dirname "$0")"/LMBfront.roff;
+       cat "$(dirname "$0")"/an.tmac;
        "$(dirname "$0")"/prepare.pl "$1";
 ) \
 | preconv \
 | pic \
 | tbl \
 | eqn -Tpdf \
-| (
-       troff -Tpdf -ms <"$(dirname "$0")"/LMBfront.ms;
-       troff -Tpdf -M"$(dirname "$0")" -mandoc -manmark \
-               -F"$(dirname "$0")" -dpaper=a4;
-) \
+| troff -Tpdf -F"$(dirname "$0")" -dpaper=a4 \
 | gropdf -F"$(dirname "$0")" -pa4;
index 5a4aad42995d824b54b38776121807a51716618f..d4294185622576c8027607079366044483ffabca 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/perl -w
 #
-#      BuildLinuxMan.pl        : Build Linux manpages book
-#      Deri James              : 15 Dec 2022
+#      BuildLinuxMan.pl                : Build Linux manpages book
+#      Deri James (& Brian Inglis)     : 15 Dec 2022
 #
 #      Params:-
 #
 #
 
 use strict;
+use File::Basename;
 
-my $dir=shift || '.';
-my @aliases=`egrep -l '^\\.so' $dir/man*/*`;
-my %alias;
-my %target;
 my $inTS=0;
 my $inBlock=0;
 
@@ -47,81 +44,66 @@ my %Sections=
        "9"     => "Kernel Developer's Manual",
 );
 
-my $Section='';
+my $dir=shift || '.';
+my $dir2=$dir;
+$dir2=~tr[.][_];
+my %files;
+my %aliases;
+my %target;
 
-LoadAlias();
-BuildBook();
+foreach my $al (`grep -E '^\\.so' $dir/man*/*`)
+{
+       #$al=~tr[.][_];
+       $al=~m/^$dir\/man\d[a-z]*\/(.*):\.\s*so\s*man\d[a-z]*\/(.*)/o;
 
-# Aliases are the man pages which .so another man page, so build a hash of them so
-# that when we are processing referenced man page we can add the target for the
-# bookmark.
+       $aliases{$1}=$2;
+}
 
-sub LoadAlias
+foreach my ($k,$v) (%aliases)
 {
-       foreach my $fn (@aliases) {
-               chomp($fn);
-               my (@pth)=split('/',$fn);
-               my $nm=pop(@pth);
-               my $bkmark="$1_$2" if $nm=~m/(.*)\.(\w+)/;
-
-               if (open(F,"<$fn")) {
-                       while (<F>) {
-                               next if m/^\.\\"/;
-
-                               if (m/^.so\s+(man\w+\/(.+)\.(.+?))$/) {
-                                       $alias{$bkmark}=["$2_$3",$2,$3];
-                                       push(@{$target{"$2_$3"}},$bkmark);
-                                       last;
-                               } else {
-                                       print STDERR "Alias fail: $fn\n";
-                               }
-                       }
-
-                       close(F);
-               } else {
-                       print STDERR "Open fail: $fn\n";
-               }
+       while (exists($aliases{$v})) {
+               $v=$aliases{$v};
        }
 }
 
-sub BuildBook
+foreach my $fn (glob "$dir/man*/*")
 {
-       print ".pdfpagenumbering D . 1\n";
-
-       foreach my $fn (sort glob("$dir/man*")) {
-               BuildSec($fn);
-       }
+       my ($nm,$sec)=GetNmSec($fn,qr/\.\d[a-z]*/);
+       $files{"${nm}.$sec"}=[$fn,(exists($aliases{"${nm}.$sec"}))?$aliases{"${nm}.$sec"}:"${nm}.$sec"];
 }
 
-sub BuildSec
+my $Section='';
+
+BuildBook();
+
+sub BuildBook
 {
-       my $manSdir=shift;
+       print ".pdfpagenumbering D . 1\n.nr PDFOUTLINE.FOLDLEVEL 0\n.defcolor pdf:href.colour rgb 0.00 0.25 0.75\n.pdfinfo /Title \"The Linux man-pages Book\"\n.special TINOR S\n";
 
-       foreach my $fn (sort sortman glob("$manSdir/*")) {
-               BuildPage($fn);
+       foreach my $bkmark (sort sortman keys %files) {
+               BuildPage($bkmark);
        }
 }
 
 sub BuildPage
 {
-       my $page=shift;
+       my $bkmark=shift;
 
-       my ($nm,$sec,$srt)=GetNmSec($page);
+       my $fn=$files{$bkmark}->[0];
+       my ($nm,$sec,$srt)=GetNmSec($bkmark,qr/\.[\da-z]+/);
 
-       my $bkmark="$1_$2" if $nm=~m/(.*)\.(\w+)/;
-       my $title= "$1\\($2\\)";
+       my $title= "$nm\\($sec\\)";
+
+       print ".\\\" >>>>>> $nm($sec) <<<<<<\n.lf 0 $bkmark\n";
 
        # If this is an alias, just add it to the outline panel.
 
-       if (exists($alias{$bkmark})) {
-               print ".eo\n.device ps:exec [/Dest /$alias{$bkmark}->[0] /Title ($title) /Level 2 /OUT pdfmark\n.ec\n";
-               print ".if dPDF.EXPORT .tm .ds pdf:look($bkmark) $alias{$bkmark}->[1]($alias{$bkmark}->[2])\n";
+       if (exists($aliases{$bkmark})) {
+               print ".eo\n.device ps:exec [/Dest /$aliases{$bkmark} /Title ($title) /Level 2 /OUT pdfmark\n.ec\n.fl\n";
                return;
        }
 
-       print ".\\\" >>>>>> $1($2) <<<<<<\n.lf 0 $bkmark\n";
-
-       if (open(F,'<',$page)) {
+       if (open(F,'<',$fn)) {
                while (<F>) {
                        if (m/^\.\\"/) {
                                print $_;
@@ -139,13 +121,22 @@ sub BuildPage
                        next if !$_;
 #                      s/^\s+//;
 
-                       if (m/^\.BR\s+([-\w\\.]+)\s+\((.+?)\)(.*)/) {
+                       s/\\-/-/g if /^\.[BM]R\s+/;
+
+                       if (m/^\.BR\s+([-\w\\.]+)\s+\((.+?)\)(.*)/ or m/^\.MR\s+([-\w\\.]+)\s+(\w+)\s+(.*)/) {
                                my $bkmark="$1";
                                my $sec=$2;
                                my $after=$3;
+                               $after=~s/\s\\".*//;
                                my $dest=$bkmark;
                                $dest=~s/\\-/-/g;
-                               $_=".MR \"$bkmark\" \"$sec\" \"$after\" \"$dest\"";
+
+                               if (exists($files{"${bkmark}.$sec"})) {
+                                       my $dest=$files{"${bkmark}.$sec"}->[1];
+                                       $_=".pdfhref L -D \"$dest\" -A \"$after\" -- \\fI$bkmark\\fP($sec)";
+                               } else {
+                                       $_=".IR ".substr($_,4);
+                               }
                        }
 
                        s/^\.BI \\fB/.BI /;
@@ -162,7 +153,7 @@ sub BuildPage
                                        $inBlock+=()=$c=~m/T\{/g;
                                        $inBlock-=()=$c=~m/T\}/g;
 
-                                       my $mtch=$c=~s/\s*\\fB([-\w.]+)\\fP\((\w+)\)/\n.MR $1 $2 \\c\n/g;
+                                       my $mtch=$c=~s/\s*\\fB([-\w.]+)\\fP\((\w+)\)/doMR($1,$2)/ge;
                                        $c="T{\n${c}\nT}" if $mtch and !$inBlock;
                                }
 
@@ -171,25 +162,23 @@ sub BuildPage
                        }
 
                        if (m/^\.TH\s+([-\w\\.]+)\s+(\w+)/) {
+
                                # if new section add top level bookmark
+
                                if ($sec ne $Section) {
-                                       print ".nr PDFOUTLINE.FOLDLEVEL 1\n.fl\n";
+                                       print ".nr PDFOUTLINE.FOLDLEVEL 1\n";
                                        print ".pdfbookmark 1 $Sections{$sec}\n";
                                        print ".nr PDFOUTLINE.FOLDLEVEL 2\n";
                                        $Section=$sec;
                                }
+
                                print "$_\n";
 
                                # Add a level two bookmark. We don't set it in the TH macro since the name passed
                                # may be different from the filename, i.e. file = unimplemented.2, TH = UNIMPLEMENTED 2
-                               print ".pdfbookmark -T $bkmark 2 $1($2)\n";
 
-                               # If this page is referenced by an alias plant a destination label for the alias.
-                               if (exists($target{$bkmark})) {
-                                       foreach my $targ (@{$target{$bkmark}}) {
-                                               print ".pdf*href.set $targ\n";
-                                       }
-                               }
+                               print ".pdfbookmark -T $bkmark 2 $nm($sec)\n";
+
                                next;
                        }
                        print "$_\n";
@@ -198,27 +187,60 @@ sub BuildPage
        }
 }
 
+sub doMR
+{
+       my $nm=shift;
+       my $sec=shift;
+
+       if (exists($files{"${nm}.$sec"})) {
+               return("\n.pdfhref L -D \"$files{\"${nm}.$sec\"}->[1]\" -A \"\\c\" -- \\fI$nm\\fP($sec)\n");
+       } else {
+               return("\\fI$nm\\fP($sec)");
+       }
+}
+
 sub GetNmSec
 {
-       my (@pth)=split('/',shift);
-       my $nm=pop(@pth);
-       my $sec=substr(pop(@pth),3);
+       my ($nm,$pth,$sec)=fileparse($_[0],$_[1]);
+       $sec=substr($sec,1);
        my $srt=$nm;
+       $srt=~s/\..+?$//;
        $srt=~s/^_+//;
-       $srt="$sec/$srt";
+       $srt=$1.sprintf("%04d",$2) if $srt=~m/^(.+)(\d+)$/;
+       #$srt="$sec/$srt";
        return($nm,$sec,$srt);
 }
 
+# add rpmvercmp
+#use RPM::VersionSort;
+#use Sort::Versions;
+
 sub sortman
 {
 # Sort - ignore case but frig it so that intro is the first entry.
 
-       my (undef,$s1,$c)=GetNmSec($a);
-       my (undef,$s2,$d)=GetNmSec($b);
+       my (undef,$s1,$c)=GetNmSec($a,qr/\.\d[a-z]*/);
+       my (undef,$s2,$d)=GetNmSec($b,qr/\.\d[a-z]*/);
 
        my $cmp=$s1 cmp $s2;
+
        return $cmp if $cmp;
-       return -1 if ($c=~m/\/intro/ and $d!~m/\/intro/);
-       return  1 if ($d=~m/\/intro/ and $c!~m/\/intro/);
-       return (lc($c) cmp lc($d));
+       return -1 if ($c=~m/^intro/ and $d!~m/^intro/);
+       return  1 if ($d=~m/^intro/ and $c!~m/^intro/);
+       $c=~tr[-_(][!" ];
+       $d=~tr[-_(][!" ];
+       $cmp=lc($c) cmp lc($d);
+       return($c cmp $d) if $cmp == 0;
+       return($cmp);
+}
+
+sub strhex
+{
+       my $res='';
+
+       foreach my $c (split('',$_[0])) {
+               $res.=sprintf("%02X",ord($c));
+       }
+
+       return($res);
 }
diff --git a/scripts/LinuxManBook/utp.mac b/scripts/LinuxManBook/utp.mac
deleted file mode 100644 (file)
index ed9027a..0000000
+++ /dev/null
@@ -1,742 +0,0 @@
-.ig
-vim:syntax=off
-
-Macros for typesetting _Unix Text Processing_.
-Based on the macros from Chapter 17 and Appendix F
-of that book.
-
-Adapted by Jon Snader as part of a project to make this classic
-book available again.
-
-Version of 16 November 2002
-..
-.RT
-.nr nH 0                \" don't number [ABCD]-heads
-.nr gE 0                \" don't add chapter number to [ABCD]-heads
-.nr chapter_page 0      \" avoid diag. if there's no .Se call
-.ds chapter_name
-\#
-\# Redefine LP so that it can take an argument to suppress spacing
-\#
-.de par*start*nospace
-.ds@auto-end
-.nr \\n[.ev]:pli \\$1
-.nr \\n[.ev]:pri \\$2
-.par@reset
-.ne 1v+\\n(.Vu
-..
-.de LP                 \"Non indented paragraph.  Don't skip space if \\$1 == 0
-.ie '\\$1'0' .par*start*nospace 0 0
-.el .par*start 0 0
-.nr \\n[.ev]:ai \\n[\\n[.ev]:PI]
-..
-\#
-\# Nh - set behavior of numbered headings
-\#  $1:
-\#      0 - no numbering
-\#      1 - number all headings
-\#      2 - number A-head only
-\#
-\#  $2 (if present):
-\#      0 - don't add section numbers to headers
-\#      1 - prefix headers with section number
-\#
-.de Nh
-. nr nH \\$1
-. if !'\\$2'' .nr gE \\$2
-..
-\#
-\#  Square centered vertically
-\#
-.ds square \v'-.25v'\s6\(sq\s0\v'.25v'
-\#
-\# Special A-head for UTP
-\#
-.de utp_Ah
-.sp 26p
-.RT
-.pdfbookmark 2 \\$1
-.ne 6
-.ps 14
-.vs 16
-.lg 0
-.ce
-\fB\*[square]  \\$1  \*[square]\fP
-.LP 0
-.lg
-.sp 18p
-.ns
-.if \\n[Ref] .tm Ah:   \\*[PDFBOOKMARK.NAME]   \\n(PN  \\$1
-..
-\#
-\#  The [ABCD]-head macros
-\#
-.de standard_Ah                        \" A-head. $1: title
-.sp 26p
-.RT
-.ne 6
-.ps 14
-.vs 16
-.lg 0
-.tr aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ
-\fB\c
-.if \\n[nH] \{.         \"if producing numbered headings
-.      ie \\n[gE] .sec# 2  \" if Se (chapter) macro is
-.                                              \" numbered, then this is on the second level
-.      el .sec# 1          \" otherwise it's on the first level
-.\}
-\&\\$1\fP
-.LP 0                   \" reset paragraph, but not font size, etc.
-.tr aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz
-.lg
-.sp 18p
-.ns
-..
-.als Ah standard_Ah
-\#
-.de Bh                  \" B-head. $1: title
-.sp 23p
-.pdfbookmark 3 \\$1
-.RT
-.ne 6
-.ps 14
-.vs 16
-.lg 0
-\fB\c
-.if '\\n[nH]'1' \{.     \"if producing numbered headings
-.      ie \\n[gE] .sec# 3  \" if Se (chapter) macro is
-.                                              \" numbered, then this is on the third level
-.      el .sec# 2          \" otherwise it's on the second level
-.\}
-\&\\$1\fP
-.LP 0                   \" reset paragraph, but not font size, etc.
-.lg
-.sp 15.5p
-.ns
-..
-\#
-.de Ch                  \" C-head. $1: title
-.sp 18p
-.RT
-.ne 6
-.ps 12
-.vs 14
-.lg 0
-\fB\c
-.if '\\n[nH]'1' \{.     \"if producing numbered headings
-.      ie \\n[gE] .sec# 4  \" if Se (chapter) macro is
-.                                              \" numbered, then this is on the fourth level
-.      el .sec# 3          \" otherwise it's on the third level
-.\}
-\&\\$1\fP
-.LP 0                   \" reset paragraph, but not font size, etc.
-.lg
-.sp 12p
-.ns
-..
-\#
-.de Dh                  \" D-head. $1: title
-.sp 18p
-.RT
-.ne 6
-.ps 10
-.vs 12
-.lg 0
-\fB\c
-.if '\\n[nH]'1' \{.     \"if producing numbered headings
-.      ie \\n[gE] .sec# 5  \" if Se (chapter) macro is
-.                                              \" numbered, then this is on the fifth level
-.      el .sec# 4          \" otherwise it's on the fourth level
-.\}
-\&\\$1.\fP
-.lg
-..
-\#
-\# The Section macro
-\#
-\#  This is for Chapters and Appendices
-\#
-.de Se                  \" Section. $1: number, $2: name
-.                       \" $3: type (Chapter, Appendix, ...)
-.                                              \" $4: non-null => don't map to uppercase
-.if e \{\
-\&
-.bp
-.\}
-.ds chapter_name \\$2
-.ie !'\\$1'' \{.               \" If we have a section number
-.       utpbookmark -T "\\$3\\$1" 1 "\\$1. \\$2"
-.      ds chapter_head \\$1
-.      nr is_alpha 0
-.      if '\\$1'A' .set_section 1
-.      if '\\$1'B' .set_section 2
-.      if '\\$1'C' .set_section 3
-.      if '\\$1'D' .set_section 4
-.      if '\\$1'E' .set_section 5
-.      if '\\$1'F' .set_section 6
-.      if '\\$1'G' .set_section 7
-.      if '\\$1'H' .set_section 8
-.      if '\\$1'I' .set_section 9
-.      if '\\$1'J' .set_section 10
-.      if '\\$1'K' .set_section 11
-.      if '\\$1'L' .set_section 12
-.      if '\\$1'M' .set_section 13
-.      if '\\$1'N' .set_section 14
-.      if '\\$1'O' .set_section 15
-.      if '\\$1'P' .set_section 16
-.      if '\\$1'Q' .set_section 17
-.      if '\\$1'R' .set_section 18
-.      if '\\$1'S' .set_section 19
-.      if '\\$1'T' .set_section 20
-.      if '\\$1'U' .set_section 21
-.      if '\\$1'V' .set_section 22
-.      if '\\$1'W' .set_section 23
-.      if '\\$1'X' .set_section 24
-.      if '\\$1'Y' .set_section 25
-.      if '\\$1'Z' .set_section 26
-.      if !\\n[is_alpha] \{\
-.              nr section \\$1
-.              nr intH1 \\$1
-.      \}
-.\}
-.el \{.                 \" Illegal Chapter Appendix number
-.      nr section 0
-.       utpbookmark -T \\$2 1 \\$2
-.                       \" Might be Preface, etc. so no error diag.
-.\}
-.nr chapter_page2 1            \" Next page starts a chapter, so no header
-.if \\n[%]>1 .bp
-.nr PN \\n[%]
-.ie '\\$3'NONE' .af PN i
-.el .af PN 1
-.nr chapter_page 1      \" This page starts a chapter, number at bottom
-.if !\\n[gE] .nr intH1 0
-.nr intH2 0              \" rescind lower level numbering
-.nr intH3 0
-.nr intH4 0
-.nr intH5 0
-.nr fig_num 0            \" Reset figure number
-.nr table_num 0          \" Reset table number
-.format_section "\\$1" "\\$2" \\$3 \\$4
-.ie '\\$1'' \{\
-.ie '\\$2'' .if \\n[Ref] .tm   Se:     \\*[PDFBOOKMARK.NAME]   \\n(PN          \\$3
-.el .if \\n[Ref] .tm Se:       \\*[PDFBOOKMARK.NAME]   \\n(PN  \\$1    \\$2
-.\}
-.el .if \\n[Ref] .tm Se:       \\*[PDFBOOKMARK.NAME]   \\n(PN  \\$1    \\$2
-..
-\#
-\# Set section number for alphabet chapters (appendices)
-\#
-.de set_section
-.nr intH1 \\$1
-.af intH1 A
-.nr section \\$1
-.nr is_alpha 1
-..
-\#
-\# Draw a horizontal line
-\#
-.de horizontal_line
-.br
-\l'\\n[.l]u-\\n[.i]u\&\\$1'
-.br
-..
-.als Hl horizontal_line
-\#
-\#  Standard Section Formatting Routine
-\#
-.de format_standard_section
-.RT
-.in 0
-.lg 0
-.if '\\$4'' .tr aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ
-.sp
-.na
-.\" Set section type--default is Chapter
-.ie !'\\$3'' \{\
-.      ie '\\$3'NONE' .ds chapter_type
-.      el .ds chapter_type \\$3
-.\}
-.el .ds chapter_type Chapter
-.\" If there is a section number, output Type and section number
-.if !'\\$1'' \s14\fB\\*[chapter_type] \\$1\fP\s0
-.\" If there is no section number, but there is a type, then output it
-.if '\\$1'' .if !'\\$3'' \s14\fB\\*[chapter_type]\fP\s0
-.sp 5p
-.\" Print the section title if there is one
-\#.if !'\\$2'' \s14\fB\\$2\fP\s0
-.if !'\\$2'' \{\
-.ps 14
-.B
-\&\\$2
-.R
-.ps \\n[PS]                  \" Reset to PS in case of inline \s
-.\}
-.sp 6p
-.ad b                        \" Adjust both margins
-.horizontal_line             \" Draw horizontal line
-.if '\\$4'' .tr aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz
-.sp 3
-.ns
-..
-.als format_section format_standard_section
-\#
-\# numbered header Macros
-\# Special version of NH to generate just the string
-\# Used internally.
-\#
-.de sec#
-.nr NS \\$1                \" Current level
-.if !\\n[.$] .nr NS 1      \" Default is level 1
-.if !\\n[NS] .nr NS 1      \" In case it's NULL or negative
-.nr intH\\n[NS] +1         \" Increment count on current level
-.\" Rescind lower levels
-.if !\\n[NS]-4 .nr intH5 0
-.if !\\n[NS]-3 .nr intH4 0
-.if !\\n[NS]-2 .nr intH3 0
-.if !\\n[NS]-1 .nr intH2 0
-.\" Build up the string
-.if !\\$1 .if \\n[.$] .nr intH1 1
-.ds SN \\n[intH1]
-.ie \\n[NS]-1 .as SN .\\n[intH2]
-.el .as SN .               \" either x.y or x.
-.if \\n[NS]-2 .as SN .\\n[intH3]
-.if \\n[NS]-3 .as SN .\\n[intH4]
-.if \\n[NS]-4 .as SN .\\n[intH5]
-'ti \\n[.i]u
-\\*[SN]                    \" print answer
-..
-\#
-\# Figure start and end macros
-\#
-.de Fs                      \" start figure $1: reserved space $2: float figure
-.RT
-.ie 'F'\\$2' \{.            \" if figure can float
-.      nr floating_keep 1
-.      KF
-.\}
-.el .nr floating_keep 0
-.if !'\\$1'' \{.            \" if space specified
-.      ne \\$1
-.      fl
-.      rs
-.      sp \\$1
-.\}
-..
-.de Fe                      \" end figure $1: title
-.sp
-.nr fig_num +1                         \" increment figure counter
-.ie \\n[section] .ds figure \\*[chapter_head].\\n[fig_num]
-.el .ds figure \\n[fig_num]
-.ce
-\f[BI]Figure \\*[figure] \\$1\fP
-.sp
-.if \\n[floating_keep] .KE
-..
-\#
-\# Table start and end macros
-\#
-.de Ts                       \" table start $1: title
-.nr table_num +1             \" increment table number
-.ie \\n[section] .ds table \\*[chapter_head].\\n[table_num]
-.el .ds table \\n[table_num]
-.sp
-.ce
-\f[BI]Table \\*[table] \\$1\fP
-.LP
-..
-.de Te
-.RT
-.sp
-..
-\#
-\# Numbered lists
-\#
-.nr l0 0 1
-.de Ls
-.\" list start $1: A - ALPHA
-.\"                a - alpha
-.\"                B - bullet
-.\"                N - numeric
-.\"                R - ROMAN NUMERALS
-.\"                r - roman numerals
-.\"            $2: indent
-.\"            $3: alternate bullet character
-.br
-.if !'\\$1'A' .if !'\\$1'a' .if !'\\$1'B' .if !'\\$1'N' \
-.      if   !'\\$1'R' .if !'\\$1'r' .if !'\\$1'' \
-.      tm Ls: Need A, a, B, N, R, or r as type
-.nr l\\n+[l0] 0 1
-.ie '\\$1'' \{.                      \" set defaults
-.      if '\\n[l0]'1' .af l\\n[l0] 1    \"numeric at 1st level
-.      if '\\n[l0]'2' .af l\\n[l0] a    \"alpha at 2nd level
-.      if '\\n[l0]'3' .af l\\n[l0] i    \"roman at 3rd level
-.      if '\\n[l0]'4' .ds l\\n[l0] \(bu \"bullet at 4th level
-.      if '\\n[l0]'5' .ds l\\n[l0] \-   \"dash at 5th level
-.      if \\n[l0]-5 .ds l\\n[l0] \(bu   \"bullet above 5th level
-.      if \\n[l0]-3 .nr l\\n[l0] 0-1    \"mark bullet and dash as non-incrementing
-.\}
-.el \{\
-.      if '\\$1'A' .af l\\n[l0] A
-.      if '\\$1'a' .af l\\n[l0] a
-.      if '\\$1'B' \{\
-.              ie '\\$3'' .ds l\\n[l0] \(bu
-.              el .ds l\\n[l0] \\$3
-.              nr l\\n[l0] 0-1             \"mark as non-incrementing
-.      \}
-.      if '\\$1'R' .af l\\n[l0] I
-.      if '\\$1'r' .af l\\n[l0] i
-.\}
-.ie !'\\$2'' .nr i\\n[l0] \\$2      \"set list indent
-.el .nr i\\n[l0] 5                  \"default indent
-.RS
-..
-.de Li                       \" List start $1 == 0: no blank line preceding
-.br
-.if '\\$1'0' .ns
-.ie '\\n[l\\n[l0]]'-1' .intIP "\\*[l\\n[l0]]" "\\n[i\\n[l0]]"
-.el \{\
-.      nr l\\n[l0] +1
-.      intIP "\\n[l\\n[l0]]." "\\n[i\\n[l0]]"
-.\}
-..
-.de Le                       \" List end $1 == 0: no blank line after
-.br
-.rr l\\n[l0]                 \" remove number registers
-.rr i\\n[l0]
-.rm l\\n[l0]                 \" and string register, if any
-.nr l0 -1                    \" back one level of nesting
-.RE
-.ie !\\n[l0] \{\
-.      ie '\\$1'0' .LP 0
-.      el .LP
-.\}
-.el .if !'\\$1'0' .sp \\n[PD]u
-..
-\#
-\# intIP - internal version of IP that centers tag
-\#
-.de intIP
-.sp \\n[PD]u
-.in \\n[\\n[.ev]:il]u*\\n[PI]u-\\n[PI]u+\\$2n
-.nr indent1 \\$2n/2u+\w'\\$1' \" amount to move left
-\#.nr indent2 \\$2n+\w'\\$1'  \" amount to move back
-\#.ta \\n[indent2]u
-.ta \\n[indent1]u
-.ti -\\n[indent1]u
-\\$1\t\c
-..
-\#
-\# Printout and listing macros
-\#
-.ev printout                 \" set up the listing environment
-.ns
-.ps 9
-.vs 10
-.ft C
-.nf
-.ev
-.de Ps                       \" printout start $1: indent
-.br
-.ev printout
-.sp \\n[PD]u
-.ie !'\\$1'' .in +\\$1n
-.el .in +5n
-..
-.de Pe                       \" printout end $1: non-null => no following space
-.br
-.if '\\$1'' .sp \\n[PD]u
-.in
-.ev
-..
-\#
-\# X[1-4]:  Side by side virtual display screens
-\# Contributed by Heinz-Jürgen Oertel
-\#
-.\" Macro definition
-.\" window width
-.\" Should be calculated, so that the width is 25 equal spaced chars
-.nr my_wid \w'\f(CW12345678901234567890123456\fP'
-.de X1
-.sp
-.mk x_box
-.nf
-.\" left and right page offset
-.po +(u;\\n[.ll]/40)
-.ll \n[my_wid]u
-.in +1n
-.CW
-..
-.de X2
-.mk here
-.in -1n
-.draw_screen \n[my_wid]u \\n[here]u-\\n[x_box]u+\\n[.v]u
-.po +(u;\n[my_wid])
-.\" line length of the centered text
-.ll (u;(\\n[LL]u)-(2*\n[my_wid]u)-(\\n[LL]/20u))
-.sp |\\n[x_box]u
-.ce 10
-.R
-..
-.de X3
-.ce 0
-.sp |\\n[x_box]u
-.po +(u;(\\n[LL]u)-(2*\n[my_wid]u)-(\\n[LL]/20u))
-.ll \n[my_wid]u
-.nf
-.in +1n
-.CW
-..
-.de X4
-.in -1n
-.draw_screen \n[my_wid]u \\n[here]u-\\n[x_box]u+\\n[.v]u
-.R
-.fi
-.po \\n(POu
-.ll \\n(LLu
-..
-\#
-\# Helvetica font change macros
-\#
-.de H                        \" Helvetica
-.ie !\\n[.$] .ft H
-.el \&\\$3\fH\\$1\fP\\$2
-..
-.de HB                       \" Helvetica Bold
-.ie !\\n[.$] .ft HB
-.el \&\\$3\f[HB]\\$1\fP\\$2
-..
-.de HI                       \" Helvetica Italic
-.ie !\\n[.$] .ft HI
-.el \&\\$3\f[HI]\\$1\fP\\$2
-..
-\#
-\#  Screen Boxes
-\#
-.de draw_screen              \" Draw box with rounded corners, $1: wid $2: ht
-.nr radius (((\\$1)<?(\\$2))/4u)<?.25i
-\v'-\\n[radius]u'\D'a \\n[radius]u 0 0 \\n[radius]u'\c
-\D'l (\\$1)-(2u*\\n[radius]u) 0'\c
-\D'a 0 -\\n[radius]u \\n[radius]u 0'\D'l 0 -(\\$2)+(2u*\\n[radius]u)'\c
-\D'a -\\n[radius]u 0 0 -\\n[radius]u'\D'l -(\\$1)+(2u*\\n[radius]u) 0'\c
-\D'a 0 \\n[radius]u -\\n[radius]u 0'\D'l 0 (\\$2)-(2u*\\n[radius]u)'
-..
-.de SS
-.nr li_save \\n[\\n[.ev]:li]
-.nr ri_save \\n[\\n[.ev]:ri]
-.nr \\n[.ev]:li +3n
-.nr \\n[.ev]:ri +3n
-.br
-.sp \\n[SS_prefix]u
-.ie \\n[.$] \{\
-.      nr width \\$1
-.      nr height \\$2
-.      mk screen_start
-.\}
-.el .nr width 0
-.di screen_div
-.sp .5v
-.in +3n                      \" Leave extra room for the rounded corners
-.ll -3n
-.lt -3n
-\&
-..
-.de SE
-.br
-.di
-.ne \\n[dn]u
-.ev nf
-.screen_div
-.ev
-.in -3n
-.ll +3n
-.lt +3n
-.nr \\n[.ev]:li \\n[li_save]
-.nr \\n[.ev]:ri \\n[ri_save]
-.ie !\\n[width] \{\
-.      mk screen_end
-\#.    draw_screen \\n[dl]u+3n \\n[dn]u+\\n[.v]u
-.      draw_screen \\n[.l]u \\n[dn]u+\\n[.v]u
-.\}
-.el \{\
-.      sp |\\n[screen_start]u+\\n[height]u-\\n[.v]u
-.      mk screen_end
-.      draw_screen \\n[width]u \\n[height]u
-.\}
-.sp |\\n[screen_end]u+1
-..
-\#
-\# Notes macros
-\#
-.nr note_counter 0
-.nr rnotes 0
-.ev notes
-.par*env-init
-.ll \n[LL]u
-.lt \n[LL]u
-.ps \n[PS]
-.vs \n[VS]
-.ev
-.de Rn                       \" Reviewer note, $1: note
-.sp
-\fBNote to reviewers:\fP \\$1
-.sp
-.ev notes
-.da rev_notes
-.sp 0.2v
-.in 0
-.ie \\n[do-page] \(sq Page \\n[PN] (\\*[page-utp]): \\$1
-.el \(sq Page \\n(PN: \\$1
-.br
-.da
-.nr rnotes 1
-.ev
-..
-.de Pn                       \" Personal note, $1: note
-.ev notes
-.if \\n[note_counter]<1 .nr note_counter 0 1
-.da pers_notes
-.br
-.IP \\n+[note_counter]. 5n
-\\$1
-.ie \\n[do-page] \ (Page \\n[PN]/\\*[page-utp])
-.el \ (Page \\n(PN)
-.br
-.da
-.ev
-..
-\#
-\# End Macro
-\#
-\# Output diverted material
-\#
-.de EM
-.br
-.if \\n[rnotes]=1 \{\
-\&\c
-'      bp
-.      ce
-\fBNotes to Reviewers\fP
-.      sp 2
-.      ev notes
-.      nf
-.      rev_notes
-.      ev
-.\}
-.if \\n[note_counter]>0 \{\
-.      br
-\&\c
-'      bp
-.      ce
-\fBPersonal Notes\fP
-.      sp 2
-.      ev notes
-.      nf
-.      pers_notes
-.      ev
-.\}
-..
-\#
-\# UTP top and bottom page processing
-\#
-.de utp_top
-.ev header_footer
-.nr PN \\n[%]
-.if !\\n[chapter_page2] \{.   \" if this page doesn't start a chapter
-.      ie o .tl ''\\*[chapter_name]'\\n[PN]'
-.      el .tl '\\n[PN]'\*[square]  Unix Text Processing  \*[square]''
-.\}
-.ev
-..
-.de utp_bottom
-.ev header_footer
-.if \\n[chapter_page] \{\
-.      tl ''\\n[PN]''
-.      nr chapter_page 0
-.      nr chapter_page2 0
-.\}
-.ev
-..
-\#.de page
-\#.mk page-vpos
-\#.nr page-hpos \\n[.k]
-\#.po \\n[PO]u-4n
-\#.br
-\#\\$1
-\#.br
-\#.po \\n[PO]u
-\#.sp |\\n[page-vpos]u
-\#\h'|\\n[page-hpos]u'
-\#..
-.de do-page                   \" Enable the .page macro
-.nr do-page 1
-..
-.de page                      \" Capture the original UTP page numbers
-.ds page-utp \\$1
-.if \\n[do-page] \{\
-.      mk page-pos
-.      ev page-env
-'      di page-num
-'      nf
-\\$1
-.      ev
-.      di
-.      mk page-trap
-.      nr page-trap +.1v
-.      wh \\n[page-trap]u page-put
-.\}
-..
-.de page-put                  \" Place the UTP page number in the left margin
-.mk page-end
-.wh \\n[page-trap]u
-'sp |\\n[page-pos]u
-.ev page-env
-'po \\n[PO]u-5n
-'fi
-.page-num
-.br
-.ev
-'po \\n[PO]u
-'sp |\\n[page-end]u
-..
-.de ix
-.ie '\\n(.z'' \{\
-.   if !'\\$1'%end' \{\
-.      ds ixbk ix:bm\\n+[ixno]
-.      pdfhref M -N \\*[ixbk]
-.   \}
-.   if \\n[Ref] .tm ix: \\$*   \\n%    \\*[ixbk]
-.\}
-.el \\!.ix \\$*
-..
-\#
-\# Set defaults for UTP
-\#
-.de utp
-.ps 10
-.vs 12
-.nr PS 10
-.nr VS 12
-.nr SS_prefix 1v
-.nr do-page 0
-.Nh 0 0
-.als Ah utp_Ah
-.als chapter Se
-.als PT utp_top
-.als BT utp_bottom
-.ev header_footer
-.ll \\n[LL]u
-.lt \\n[LL]u
-.ps \\n[PS]
-.vs \\n[VS]
-.ev
-..
-.de utpbookmark
-.ie '\\*[.T]'ps' \{\
-.    pdfhref M -N \\$2 -- \\$4
-.    if !dpdf:href.map .tm gropdf-info:href \\$2 \\$4
-.    pdfbookmark \\$3 \\$4
-.\}
-.el .pdfbookmark \\$*
-..
-.em EM