summaryrefslogtreecommitdiffstats
path: root/scripts/LinuxManBook/BuildLinuxMan.pl
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/LinuxManBook/BuildLinuxMan.pl')
-rwxr-xr-xscripts/LinuxManBook/BuildLinuxMan.pl249
1 files changed, 249 insertions, 0 deletions
diff --git a/scripts/LinuxManBook/BuildLinuxMan.pl b/scripts/LinuxManBook/BuildLinuxMan.pl
new file mode 100755
index 0000000..7d96057
--- /dev/null
+++ b/scripts/LinuxManBook/BuildLinuxMan.pl
@@ -0,0 +1,249 @@
+#!/usr/bin/perl -w
+#
+# BuildLinuxMan.pl : Build Linux manpages book
+# Deri James : 15 Dec 2022
+#
+# Params:-
+#
+# $1 = Directory holding the man pages
+#
+# (C) Copyright 2022, Deri James
+#
+# This program 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 2
+# of the License, or (at your option) any later version.
+#
+# This program 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
+# (http://www.gnu.org/licenses/gpl-2.0.html).
+#
+
+use strict;
+
+my $dir=shift || '.';
+my @aliases=`egrep -l '^\\.so' $dir/man*/*`;
+my %alias;
+my %target;
+my $inTS=0;
+my $inBlock=0;
+
+my %Sections=
+(
+ "1" => "General Commands Manual",
+ "2" => "System Calls Manual",
+ "2type" => "System Calls Manual (types)",
+ "3" => "Library Functions Manual",
+ "3const" => "Library Functions Manual (constants)",
+ "3head" => "Library Functions Manual (headers)",
+ "3type" => "Library Functions Manual (types)",
+ "4" => "Kernel Interfaces Manual",
+ "5" => "File Formats Manual",
+ "6" => "Games Manual",
+ "7" => "Miscellaneous Information Manual",
+ "8" => "System Manager's Manual",
+ "9" => "Kernel Developer's Manual",
+);
+
+my $Section='';
+
+LoadAlias();
+BuildBook();
+
+my $cmdstring="-Tpdf -k -pet -M. -F. -mandoc -manmark -dpaper=a4 -P-pa4 -rC1 -rCHECKSTYLE=3";
+
+system("groff -Tpdf -ms LMBfront.t -Z > LMBfront.Z");
+system("groff -z -dPDF.EXPORT=1 -dLABEL.REFS=1 T $cmdstring 2>&1 | LC_ALL=C grep '^\\. *ds' | groff -Tpdf $cmdstring - T -Z > LinuxManBook.Z");
+system("./gropdf -F. LMBfront.Z LinuxManBook.Z > LinuxManBook.pdf");
+unlink "LinuxManBook.Z","LMBfront.Z"; # If you want to clean up
+
+# 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.
+
+sub LoadAlias
+{
+ 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";
+ }
+ }
+}
+
+sub BuildBook
+{
+ open(BK,">T");
+
+ foreach my $fn (sort sortman glob("$dir/man*/*"))
+ {
+ my ($nm,$sec,$srt)=GetNmSec($fn);
+
+ my $bkmark="$1_$2" if $nm=~m/(.*)\.(\w+)/;
+ my $title= "$1\\($2\\)";
+
+# If this is an alias, just add it to the outline panel.
+
+ if (exists($alias{$bkmark}))
+ {
+ print BK ".eo\n.device ps:exec [/Dest /$alias{$bkmark}->[0] /Title ($title) /Level 2 /OUT pdfmark\n.ec\n";
+ print BK ".if dPDF.EXPORT .tm .ds pdf:look($bkmark) $alias{$bkmark}->[1]($alias{$bkmark}->[2])\n";
+ next;
+ }
+
+ print BK ".\\\" >>>>>> $1($2) <<<<<<\n";
+
+ if (open(F,'<',$fn))
+ {
+ while (<F>)
+ {
+ if (m/^\.\\"/)
+ {
+ print BK $_;
+ next;
+ }
+
+ chomp;
+
+# This code is to determine whether we are within a tbl block and in a text block
+# T{ and T}. This is fudge code particularly for the syscalls(7) page.
+
+ $inTS=1 if m/\.TS/;
+ $inTS=0,$inBlock=0 if m/\.TE/;
+
+ s/\r$//; # In case edited under windows i.e. CR/LF
+ s/\s+$//;
+ next if !$_;
+# s/^\s+//;
+
+ if (m/^\.BR\s+([-\w\\.]+)\s+\((.+?)\)(.*)/)
+ {
+ my $bkmark="$1";
+ my $sec=$2;
+ my $after=$3;
+ my $dest=$bkmark;
+ $dest=~s/\\-/-/g;
+ $_=".MR \"$bkmark\" \"$sec\" \"$after\" \"$dest\"";
+ }
+
+ s/^\.BI \\fB/.BI /;
+ s/^\.BR\s+(\S+)\s*$/.B $1/;
+ s/^\.BI\s+(\S+)\s*$/.B $1/;
+ s/^\.IR\s+(\S+)\s*$/.I $1/;
+
+# Fiddling for syscalls(7) :-(
+
+ if ($inTS)
+ {
+ my @cols=split(/\t/,$_);
+
+ foreach my $c (@cols)
+ {
+ $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;
+ $c="T{\n${c}\nT}" if $mtch and !$inBlock;
+ }
+
+ $_=join("\t",@cols);
+ s/\n\n/\n/g;
+ }
+
+ if (m/^\.TH\s+([-\w\\.]+)\s+(\w+)/)
+ {
+
+ # if new section add top level bookmark
+
+ if ($sec ne $Section)
+ {
+ print BK ".nr PDFOUTLINE.FOLDLEVEL 1\n.fl\n";
+ print BK ".pdfbookmark 1 $Sections{$sec}\n";
+ print BK ".nr PDFOUTLINE.FOLDLEVEL 2\n";
+ $Section=$sec;
+ }
+
+ print BK "$_\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 BK ".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 BK ".pdf*href.set $targ\n";
+ }
+ }
+
+ next;
+ }
+
+ print BK "$_\n";
+
+ }
+
+ close(F);
+
+ }
+ }
+
+ close(BK);
+}
+
+sub GetNmSec
+{
+ my (@pth)=split('/',shift);
+ my $nm=pop(@pth);
+ my $sec=substr(pop(@pth),3);
+ my $srt=$nm;
+ $srt=~s/^_+//;
+ $srt="$sec/$srt";
+ return($nm,$sec,$srt);
+}
+
+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 $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));
+}