]>
Commit | Line | Data |
---|---|---|
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 | ||
24 | use strict; | |
6d87a75a | 25 | use File::Basename; |
f882f1ee | 26 | |
f882f1ee AC |
27 | my $inTS=0; |
28 | my $inBlock=0; | |
29 | ||
30 | my %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 |
47 | my $dir=shift || '.'; |
48 | my $dir2=$dir; | |
49 | $dir2=~tr[.][_]; | |
50 | my %files; | |
51 | my %aliases; | |
f882f1ee | 52 | |
1bd48bd9 AC |
53 | foreach 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 | 63 | while (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 |
70 | foreach 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 |
79 | my $Section=''; |
80 | ||
81 | BuildBook(); | |
82 | ||
83 | sub 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 |
92 | sub 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 |
196 | sub 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 |
208 | sub 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 |
224 | sub 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 | ||
243 | sub 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 | } |