]> git.ipfire.org Git - thirdparty/man-pages.git/blame - share/mk/build/pdf/book/prepare.pl
share/mk/: build-fonts-tinos: Build TinosR from TinosR.afm
[thirdparty/man-pages.git] / share / mk / build / pdf / book / prepare.pl
CommitLineData
f882f1ee
AC
1#!/usr/bin/perl -w
2#
6d87a75a
AC
3# BuildLinuxMan.pl : Build Linux manpages book
4# Deri James (& Brian Inglis) : 15 Dec 2022
f882f1ee
AC
5#
6# Params:-
7#
8# $1 = Directory holding the man pages
9#
10# (C) Copyright 2022, Deri James
11#
12# This program is free software; you can redistribute it and/or
13# modify it under the terms of the GNU General Public License
14# as published by the Free Software Foundation; either version 2
15# of the License, or (at your option) any later version.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20# GNU General Public License for more details
21# (http://www.gnu.org/licenses/gpl-2.0.html).
22#
23
24use strict;
6d87a75a 25use File::Basename;
f882f1ee 26
f882f1ee
AC
27my $inTS=0;
28my $inBlock=0;
29
30my %Sections=
31(
11d50d9d
AC
32 "1" => "General Commands Manual",
33 "2" => "System Calls Manual",
34 "2type" => "System Calls Manual (types)",
35 "3" => "Library Functions Manual",
36 "3const" => "Library Functions Manual (constants)",
37 "3head" => "Library Functions Manual (headers)",
38 "3type" => "Library Functions Manual (types)",
39 "4" => "Kernel Interfaces Manual",
40 "5" => "File Formats Manual",
41 "6" => "Games Manual",
42 "7" => "Miscellaneous Information Manual",
43 "8" => "System Manager's Manual",
44 "9" => "Kernel Developer's Manual",
f882f1ee
AC
45);
46
6d87a75a
AC
47my $dir=shift || '.';
48my $dir2=$dir;
49$dir2=~tr[.][_];
50my %files;
51my %aliases;
f882f1ee 52
1bd48bd9
AC
53foreach my $al (`find "$dir"/man*/ -type f \\
54 | grep "\\.[[:digit:]]\\([[:alpha:]][[:alnum:]]*\\)\\?\\>\$" \\
55 | xargs grep '^\\.so' /dev/null;`)
6d87a75a
AC
56{
57 #$al=~tr[.][_];
58 $al=~m/^$dir\/man\d[a-z]*\/(.*):\.\s*so\s*man\d[a-z]*\/(.*)/o;
f882f1ee 59
6d87a75a
AC
60 $aliases{$1}=$2;
61}
f882f1ee 62
347f1eba 63while (my ($k,$v)=each %aliases)
f882f1ee 64{
6d87a75a
AC
65 while (exists($aliases{$v})) {
66 $v=$aliases{$v};
f882f1ee 67 }
f882f1ee
AC
68}
69
1bd48bd9
AC
70foreach my $fn (`find "$dir"/man*/ -type f \\
71 | grep "\\.[[:digit:]]\\([[:alpha:]][[:alnum:]]*\\)\\?\\>\$";`)
f882f1ee 72{
1bd48bd9
AC
73 $fn=~s/\n//;
74
6d87a75a
AC
75 my ($nm,$sec)=GetNmSec($fn,qr/\.\d[a-z]*/);
76 $files{"${nm}.$sec"}=[$fn,(exists($aliases{"${nm}.$sec"}))?$aliases{"${nm}.$sec"}:"${nm}.$sec"];
84396157
AC
77}
78
6d87a75a
AC
79my $Section='';
80
81BuildBook();
82
83sub BuildBook
84396157 84{
c33f7781 85 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";
84396157 86
6d87a75a
AC
87 foreach my $bkmark (sort sortman keys %files) {
88 BuildPage($bkmark);
2a6f2057
AC
89 }
90}
f882f1ee 91
2a6f2057
AC
92sub BuildPage
93{
6d87a75a 94 my $bkmark=shift;
f882f1ee 95
6d87a75a
AC
96 my $fn=$files{$bkmark}->[0];
97 my ($nm,$sec,$srt)=GetNmSec($bkmark,qr/\.[\da-z]+/);
f882f1ee 98
6d87a75a
AC
99 my $title= "$nm\\($sec\\)";
100
101 print ".\\\" >>>>>> $nm($sec) <<<<<<\n.lf 0 $bkmark\n";
f882f1ee 102
2a6f2057 103 # If this is an alias, just add it to the outline panel.
11d50d9d 104
347f1eba
D
105 # if new section add top level bookmark
106
107 if ($sec ne $Section) {
108 print ".nr PDFOUTLINE.FOLDLEVEL 1\n";
109 print ".pdfbookmark 1 $Sections{$sec}\n";
110 print ".nr PDFOUTLINE.FOLDLEVEL 2\n";
111 $Section=$sec;
112 }
113
6d87a75a
AC
114 if (exists($aliases{$bkmark})) {
115 print ".eo\n.device ps:exec [/Dest /$aliases{$bkmark} /Title ($title) /Level 2 /OUT pdfmark\n.ec\n.fl\n";
2a6f2057
AC
116 return;
117 }
11d50d9d 118
6d87a75a 119 if (open(F,'<',$fn)) {
2a6f2057
AC
120 while (<F>) {
121 if (m/^\.\\"/) {
122 print $_;
123 next;
124 }
11d50d9d 125
2a6f2057 126 chomp;
11d50d9d 127
2a6f2057
AC
128 # This code is to determine whether we are within a tbl block and in a text block
129 # T{ and T}. This is fudge code particularly for the syscalls(7) page.
11d50d9d 130
2a6f2057
AC
131 $inTS=1 if m/\.TS/;
132 $inTS=0,$inBlock=0 if m/\.TE/;
11d50d9d 133
2a6f2057
AC
134 next if !$_;
135# s/^\s+//;
11d50d9d 136
6d87a75a
AC
137 s/\\-/-/g if /^\.[BM]R\s+/;
138
347f1eba 139 if (m/^\.BR\s+([-\w\\.]+)\s+\((.+?)\)(.*)/ or m/^\.MR\s+([-\w\\.]+)\s+(\w+)\s+(.*)/ or m/^\\fB([-\w\\.]+)\\fR\((.+?)\)(.*)$/) {
2a6f2057
AC
140 my $bkmark="$1";
141 my $sec=$2;
142 my $after=$3;
6d87a75a 143 $after=~s/\s\\".*//;
2a6f2057
AC
144 my $dest=$bkmark;
145 $dest=~s/\\-/-/g;
6d87a75a
AC
146
147 if (exists($files{"${bkmark}.$sec"})) {
148 my $dest=$files{"${bkmark}.$sec"}->[1];
149 $_=".pdfhref L -D \"$dest\" -A \"$after\" -- \\fI$bkmark\\fP($sec)";
150 } else {
347f1eba 151 $_=".IR $bkmark ($sec)\\c\n$after";
6d87a75a 152 }
2a6f2057 153 }
11d50d9d 154
2a6f2057
AC
155 s/^\.BI \\fB/.BI /;
156 s/^\.BR\s+(\S+)\s*$/.B $1/;
157 s/^\.BI\s+(\S+)\s*$/.B $1/;
158 s/^\.IR\s+(\S+)\s*$/.I $1/;
11d50d9d 159
2a6f2057 160 # Fiddling for syscalls(7) :-(
11d50d9d 161
2a6f2057
AC
162 if ($inTS) {
163 my @cols=split(/\t/,$_);
164
165 foreach my $c (@cols) {
166 $inBlock+=()=$c=~m/T\{/g;
167 $inBlock-=()=$c=~m/T\}/g;
11d50d9d 168
6d87a75a 169 my $mtch=$c=~s/\s*\\fB([-\w.]+)\\fP\((\w+)\)/doMR($1,$2)/ge;
2a6f2057 170 $c="T{\n${c}\nT}" if $mtch and !$inBlock;
11d50d9d
AC
171 }
172
2a6f2057
AC
173 $_=join("\t",@cols);
174 s/\n\n/\n/g;
175 }
11d50d9d 176
347f1eba 177 s/\\&\././ if m/^.TH /;
6d87a75a 178
347f1eba 179 if (m/^\.TH\s+"?([-\w\\.]+)"?\s+"?(\w+)"?/) {
6d87a75a 180
2a6f2057
AC
181 print "$_\n";
182
183 # Add a level two bookmark. We don't set it in the TH macro since the name passed
184 # may be different from the filename, i.e. file = unimplemented.2, TH = UNIMPLEMENTED 2
11d50d9d 185
6d87a75a
AC
186 print ".pdfbookmark -T $bkmark 2 $nm($sec)\n";
187
2a6f2057 188 next;
f882f1ee 189 }
2a6f2057 190 print "$_\n";
f882f1ee 191 }
2a6f2057 192 close(F);
f882f1ee 193 }
f882f1ee
AC
194}
195
6d87a75a
AC
196sub doMR
197{
198 my $nm=shift;
199 my $sec=shift;
200
201 if (exists($files{"${nm}.$sec"})) {
202 return("\n.pdfhref L -D \"$files{\"${nm}.$sec\"}->[1]\" -A \"\\c\" -- \\fI$nm\\fP($sec)\n");
203 } else {
204 return("\\fI$nm\\fP($sec)");
205 }
206}
207
f882f1ee
AC
208sub GetNmSec
209{
6d87a75a
AC
210 my ($nm,$pth,$sec)=fileparse($_[0],$_[1]);
211 $sec=substr($sec,1);
11d50d9d 212 my $srt=$nm;
6d87a75a 213 $srt=~s/\..+?$//;
11d50d9d 214 $srt=~s/^_+//;
6d87a75a
AC
215 $srt=$1.sprintf("%04d",$2) if $srt=~m/^(.+)(\d+)$/;
216 #$srt="$sec/$srt";
11d50d9d 217 return($nm,$sec,$srt);
f882f1ee
AC
218}
219
6d87a75a
AC
220# add rpmvercmp
221#use RPM::VersionSort;
222#use Sort::Versions;
223
f882f1ee
AC
224sub sortman
225{
226# Sort - ignore case but frig it so that intro is the first entry.
227
6d87a75a
AC
228 my (undef,$s1,$c)=GetNmSec($a,qr/\.\d[a-z]*/);
229 my (undef,$s2,$d)=GetNmSec($b,qr/\.\d[a-z]*/);
f882f1ee 230
11d50d9d 231 my $cmp=$s1 cmp $s2;
6d87a75a 232
11d50d9d 233 return $cmp if $cmp;
6d87a75a
AC
234 return -1 if ($c=~m/^intro/ and $d!~m/^intro/);
235 return 1 if ($d=~m/^intro/ and $c!~m/^intro/);
236 $c=~tr[-_(][!" ];
237 $d=~tr[-_(][!" ];
238 $cmp=lc($c) cmp lc($d);
239 return($c cmp $d) if $cmp == 0;
240 return($cmp);
241}
242
243sub strhex
244{
245 my $res='';
246
247 foreach my $c (split('',$_[0])) {
248 $res.=sprintf("%02X",ord($c));
249 }
250
251 return($res);
f882f1ee 252}