summaryrefslogtreecommitdiffstats
path: root/scripts/LinuxManBook/prepare.pl
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/LinuxManBook/prepare.pl')
-rwxr-xr-xscripts/LinuxManBook/prepare.pl248
1 files changed, 248 insertions, 0 deletions
diff --git a/scripts/LinuxManBook/prepare.pl b/scripts/LinuxManBook/prepare.pl
new file mode 100755
index 0000000..735cfcf
--- /dev/null
+++ b/scripts/LinuxManBook/prepare.pl
@@ -0,0 +1,248 @@
+#!/usr/bin/perl -w
+#
+# BuildLinuxMan.pl : Build Linux manpages book
+# Deri James (& Brian Inglis) : 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;
+use File::Basename;
+
+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 $dir=shift || '.';
+my $dir2=$dir;
+$dir2=~tr[.][_];
+my %files;
+my %aliases;
+my %target;
+
+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{$1}=$2;
+}
+
+while (my ($k,$v)=each %aliases)
+{
+ while (exists($aliases{$v})) {
+ $v=$aliases{$v};
+ }
+}
+
+foreach my $fn (glob "$dir/man*/*")
+{
+ my ($nm,$sec)=GetNmSec($fn,qr/\.\d[a-z]*/);
+ $files{"${nm}.$sec"}=[$fn,(exists($aliases{"${nm}.$sec"}))?$aliases{"${nm}.$sec"}:"${nm}.$sec"];
+}
+
+my $Section='';
+
+BuildBook();
+
+sub BuildBook
+{
+ 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 $bkmark (sort sortman keys %files) {
+ BuildPage($bkmark);
+ }
+}
+
+sub BuildPage
+{
+ my $bkmark=shift;
+
+ my $fn=$files{$bkmark}->[0];
+ my ($nm,$sec,$srt)=GetNmSec($bkmark,qr/\.[\da-z]+/);
+
+ 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 new section add top level bookmark
+
+ if ($sec ne $Section) {
+ print ".nr PDFOUTLINE.FOLDLEVEL 1\n";
+ print ".pdfbookmark 1 $Sections{$sec}\n";
+ print ".nr PDFOUTLINE.FOLDLEVEL 2\n";
+ $Section=$sec;
+ }
+
+ 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;
+ }
+
+ if (open(F,'<',$fn)) {
+ while (<F>) {
+ if (m/^\.\\"/) {
+ print $_;
+ 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/;
+
+ next if !$_;
+# s/^\s+//;
+
+ s/\\-/-/g if /^\.[BM]R\s+/;
+
+ if (m/^\.BR\s+([-\w\\.]+)\s+\((.+?)\)(.*)/ or m/^\.MR\s+([-\w\\.]+)\s+(\w+)\s+(.*)/ or m/^\\fB([-\w\\.]+)\\fR\((.+?)\)(.*)$/) {
+ my $bkmark="$1";
+ my $sec=$2;
+ my $after=$3;
+ $after=~s/\s\\".*//;
+ my $dest=$bkmark;
+ $dest=~s/\\-/-/g;
+
+ if (exists($files{"${bkmark}.$sec"})) {
+ my $dest=$files{"${bkmark}.$sec"}->[1];
+ $_=".pdfhref L -D \"$dest\" -A \"$after\" -- \\fI$bkmark\\fP($sec)";
+ } else {
+ $_=".IR $bkmark ($sec)\\c\n$after";
+ }
+ }
+
+ 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+)\)/doMR($1,$2)/ge;
+ $c="T{\n${c}\nT}" if $mtch and !$inBlock;
+ }
+
+ $_=join("\t",@cols);
+ s/\n\n/\n/g;
+ }
+
+ s/\\&\././ if m/^.TH /;
+
+ if (m/^\.TH\s+"?([-\w\\.]+)"?\s+"?(\w+)"?/) {
+
+ 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 $nm($sec)\n";
+
+ next;
+ }
+ print "$_\n";
+ }
+ close(F);
+ }
+}
+
+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 ($nm,$pth,$sec)=fileparse($_[0],$_[1]);
+ $sec=substr($sec,1);
+ my $srt=$nm;
+ $srt=~s/\..+?$//;
+ $srt=~s/^_+//;
+ $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,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/);
+ $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);
+}