diff options
Diffstat (limited to 'share/mk/build/pdf/book')
-rw-r--r-- | share/mk/build/pdf/book/_.mk | 51 | ||||
-rw-r--r-- | share/mk/build/pdf/book/front.roff | 33 | ||||
-rwxr-xr-x | share/mk/build/pdf/book/prepare.pl | 252 |
3 files changed, 336 insertions, 0 deletions
diff --git a/share/mk/build/pdf/book/_.mk b/share/mk/build/pdf/book/_.mk new file mode 100644 index 0000000..03595f6 --- /dev/null +++ b/share/mk/build/pdf/book/_.mk @@ -0,0 +1,51 @@ +# Copyright 2023-2024, Alejandro Colomar <alx@kernel.org> +# SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception + + +ifndef MAKEFILE_BUILD_PDF_BOOK_INCLUDED +MAKEFILE_BUILD_PDF_BOOK_INCLUDED := 1 + + +include $(MAKEFILEDIR)/build/_.mk +include $(MAKEFILEDIR)/build/man/_.mk +include $(MAKEFILEDIR)/build/fonts/_.mk +include $(MAKEFILEDIR)/build/fonts/tinos/_.mk +include $(MAKEFILEDIR)/configure/build-depends/coreutils/cat.mk +include $(MAKEFILEDIR)/configure/build-depends/groff/gropdf.mk +include $(MAKEFILEDIR)/configure/build-depends/groff-base/eqn.mk +include $(MAKEFILEDIR)/configure/build-depends/groff-base/pic.mk +include $(MAKEFILEDIR)/configure/build-depends/groff-base/preconv.mk +include $(MAKEFILEDIR)/configure/build-depends/groff-base/tbl.mk +include $(MAKEFILEDIR)/configure/build-depends/groff-base/troff.mk +include $(MAKEFILEDIR)/configure/build-depends/moreutils/sponge.mk +include $(MAKEFILEDIR)/configure/version.mk + + +MKBOOKDIR := $(MAKEFILEDIR)/build/pdf/book +MKBOOK := $(wildcard $(MKBOOKDIR)/*) + + +PDF_BOOK := $(DISTNAME).pdf +_PDFDIR := $(builddir) +_PDF_BOOK := $(_PDFDIR)/$(PDF_BOOK) + + +$(_PDF_BOOK): $(_MANPAGES) $(_DOWNLOAD) $(_TINOS) $(MKBOOK) $(MK) | $$(@D)/ + $(info $(INFO_)GROPDF $@) + $(MKBOOKDIR)/prepare.pl $(_MANDIR) \ + | $(CAT) $(MKBOOKDIR)/front.roff /dev/stdin \ + | $(PRECONV) \ + | $(PIC) \ + | $(TBL) \ + | $(EQN) -Tpdf \ + | $(TROFF) -mandoc -Tpdf -F$(_FONTSDIR) -dpaper=a4 -rC1 \ + -ran*bookmark-base-level=1 $(TROFFFLAGS) \ + | $(GROPDF) -F$(_FONTSDIR) -pa4 $(GROPDFFLAGS) \ + | $(SPONGE) $@ + + +.PHONY: build-pdf-book +build-pdf-book: $(_PDF_BOOK); + + +endif # include guard diff --git a/share/mk/build/pdf/book/front.roff b/share/mk/build/pdf/book/front.roff new file mode 100644 index 0000000..fdf1a98 --- /dev/null +++ b/share/mk/build/pdf/book/front.roff @@ -0,0 +1,33 @@ +.de Hl +.br +\l'\\n[.l]u-\\n[.i]u\&\\$1' +.br +.. +.ps 10 +.vs 12 +.po 2c +.ll 17c +.sp 2.5c +\Z@\D't 8p'@ +.Hl +\D't 0' +.sp .6i +.ad r +.ps 52 +\m[maroon]GNU/Linux\m[] +.sp 18p +.ps 16 +\f[BMB]THE MAN-PAGES BOOK\fP +.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 +.bp diff --git a/share/mk/build/pdf/book/prepare.pl b/share/mk/build/pdf/book/prepare.pl new file mode 100755 index 0000000..a074082 --- /dev/null +++ b/share/mk/build/pdf/book/prepare.pl @@ -0,0 +1,252 @@ +#!/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; + +foreach my $al (`find "$dir"/man*/ -type f \\ + | grep "\\.[[:digit:]]\\([[:alpha:]][[:alnum:]]*\\)\\?\\>\$" \\ + | xargs grep '^\\.so' /dev/null;`) +{ + #$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 (`find "$dir"/man*/ -type f \\ + | grep "\\.[[:digit:]]\\([[:alpha:]][[:alnum:]]*\\)\\?\\>\$";`) +{ + $fn=~s/\n//; + + 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 TinosR 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); +} |