4 # Copyright (C) 2010-2018 Red Hat Inc.
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are
10 # * Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
13 # * Redistributions in binary form must reproduce the above copyright
14 # notice, this list of conditions and the following disclaimer in the
15 # documentation and/or other materials provided with the distribution.
17 # * Neither the name of Red Hat nor the names of its contributors may be
18 # used to endorse or promote products derived from this software without
19 # specific prior written permission.
21 # THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
22 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
25 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 use Pod
::Simple
::Text
;
42 use Pod
::Simple
::XHTML
;
45 # https://www.redhat.com/archives/libguestfs/2013-May/thread.html#00088
46 eval { $Text::Wrap
::huge
= "overflow" };
50 podwrapper.pl - generate documentation from POD input files
59 CLEANFILES += $(man_MANS)
62 $(PODWRAPPER) --section 1 --man $@ \
63 --html $(top_builddir)/html/$@.html \
70 podwrapper.pl is a Perl script that generates various output formats
71 from POD input files that nbdkit uses for most documentation.
73 You must specify one input file, and one or more output formats. The
74 output options are I<--man>, I<--html> and I<--text> (see below).
76 In C<Makefile.am> files, use a variation of the boilerplate shown in
77 the L</SYNOPSIS> section above.
79 For information about the POD format, see L<perlpod(1)>.
97 =item B<--html> output.html
99 Write a web page to F<output.html>. If this option is not
100 given, then no web page output is produced.
106 =item B<--insert> filename:__PATTERN__
108 In the input file, replace the literal text C<__PATTERN__> with the
109 replacement file F<filename>. You can give this option multiple
112 The contents of F<filename> are treated as POD.
113 Compare and contrast with I<--verbatim>.
115 Although it is conventional to use C<__...__> (double underscores) for
116 patterns, in fact you can use any string as the pattern.
122 =item B<--man> output.n
124 Write a man page to F<output.n> (C<n> is the manual section number).
125 If this option is not given, then no man page output is produced.
133 Set the name of the man page. If not set, defaults to the basename
142 Set the section of the man page (a number such as C<1> for
143 command line utilities or C<3> for C API documentation). If
144 not set, defaults to C<1>.
150 =item B<--text> output.txt
152 Write a text file to F<output.txt>. If this option is not
153 given, then no text output is produced.
159 =item B<--verbatim> filename:__PATTERN__
161 In the input file, replace the literal text C<__PATTERN__> with the
162 replacement file F<filename>. You can give this option multiple
165 The contents of F<filename> are inserted as verbatim text, and
166 are I<not> interpreted as POD.
167 Compare and contrast with I<--insert>.
169 Although it is conventional to use C<__...__> (double underscores) for
170 patterns, in fact you can use any string as the pattern.
174 # Clean up the program name.
176 $progname =~ s{.*/}{};
179 GetOptions
("help|?" => \
$help,
181 "insert=s" => \
@inserts,
184 "section=s" => \
$section,
186 "verbatim=s" => \
@verbatims,
188 pod2usage
(1) if $help;
190 die "$progname: missing argument: podwrapper input.pod\n" unless @ARGV == 1;
191 my $input = $ARGV[0];
193 # There should be at least one output.
194 die "$progname: $input: no output format specified. Use --man and/or --html and/or --text.\n"
195 unless defined $man || defined $html || defined $text;
197 # Default for $name and $section.
198 $name = basename
($input, ".pod") unless defined $name;
199 $section = 1 unless defined $section;
201 # Note that these @...@ are substituted by ./configure.
202 my $abs_top_srcdir = "@abs_top_srcdir@";
203 my $abs_top_builddir = "@abs_top_builddir@";
204 my $package_name = "@PACKAGE_NAME@";
205 my $package_version = "@PACKAGE_VERSION@";
207 die "$progname: ./configure substitutions were not performed"
208 unless $abs_top_srcdir && $abs_top_builddir &&
209 $package_name && $package_version;
211 # Create a stable date (thanks Hilko Bengen).
213 my $filename = "$abs_top_srcdir/.git";
214 if (!$date && -d
$filename) {
215 local $ENV{GIT_DIR
} = $filename;
216 $_ = `git show -O/dev/null -s --format=%ci`;
217 $date = $1 if /^(\d+-\d+-\d+)\s/;
220 my ($day, $month, $year) = (gmtime($ENV{SOURCE_DATE_EPOCH
} || time))[3,4,5];
221 $date = sprintf ("%04d-%02d-%02d", $year+1900, $month+1, $day);
224 # Create a release string.
225 my $release = "$package_name-$package_version";
227 #print "input=$input\n";
228 #print "name=$name\n";
229 #print "section=$section\n";
230 #print "date=$date\n";
233 my $content = read_whole_file
($input);
237 my @a = split /:/, $_, 2;
238 die "$progname: $input: no colon in parameter of --insert\n" unless @a >= 2;
239 my $replacement = read_whole_file
($a[0]);
240 my $oldcontent = $content;
241 $content =~ s/$a[1]/$replacement/ge;
242 die "$progname: $input: could not find pattern '$a[1]' in input file\n"
243 if $content eq $oldcontent;
246 # Turn external links to this man page into simple cross-section links.
247 $content =~ s
,\QL
<$name($section)/\E,L</,g
;
249 # Perform @verbatims.
250 foreach (@verbatims) {
251 my @a = split /:/, $_, 2;
252 die "$progname: $input: no colon in parameter of --verbatim\n" unless @a >= 2;
253 my $replacement = read_verbatim_file
($a[0]);
254 my $oldcontent = $content;
255 $content =~ s/$a[1]/$replacement/ge;
256 die "$progname: $input: could not find pattern '$a[1]' in input file\n"
257 if $content eq $oldcontent;
260 # There should be no =encoding line present in the content (we will add one).
261 die "$progname: $input: =encoding must not be present in input\n"
262 if $content =~ /^=encoding/m;
264 $content =~ s/^=(.*)/\n=encoding utf8\n\n=$1/m;
266 # Verify sections present / not present.
267 die "$progname: $input: missing NAME section\n"
268 if $content !~ /^=head1 NAME/m;
269 die "$progname: $input: missing DESCRIPTION section\n"
270 if $content !~ /^=head1 DESCRIPTION/m;
271 die "$progname: $input: missing AUTHOR or AUTHORS section\n"
272 unless $content =~ /^=head1 AUTHOR/m;
273 die "$progname: $input: missing SEE ALSO section\n"
274 unless $content =~ /^=head1 SEE ALSO/m;
275 die "$progname: $input: missing COPYRIGHT section\n"
276 unless $content =~ /^=head1 COPYRIGHT/m;
277 die "$progname: $input: BUGS is now added automatically, do not add it to the POD file\n"
278 if $content =~ /^=head1 (REPORTING )?BUGS/m;
279 die "$progname: $input: LICENSE is now added automatically, do not add it to the POD file\n"
280 if $content =~ /^=head1 LICENSE/m;
282 # Check NAME section conformity.
283 my @lines = split /\n/, $content;
286 push @name, $_ if /^=head1 NAME/../^=head1 (?!NAME)/
288 shift @name; # remove =head1 and empty line
289 shift @name; # from beginning and end
292 die "$progname: $input: empty NAME section\n"
294 die "$progname: $input: NAME doesn't start with nbdkit\n"
295 unless $name[0] =~ m/^nbdkit/;
296 die "$progname: $input: NAME does not conform with Linux man pages standard\n"
297 if $name[0] !~ m/- [a-z]/ || $name[@name-1] =~ m/\.$/;
299 # Add standard LICENSE section at the end.
305 Redistribution and use in source and binary forms, with or without
306 modification, are permitted provided that the following conditions are
313 Redistributions of source code must retain the above copyright
314 notice, this list of conditions and the following disclaimer.
318 Redistributions in binary form must reproduce the above copyright
319 notice, this list of conditions and the following disclaimer in the
320 documentation and/or other materials provided with the distribution.
324 Neither the name of Red Hat nor the names of its contributors may be
325 used to endorse or promote products derived from this software without
326 specific prior written permission.
330 THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
331 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
332 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
333 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
334 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
335 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
336 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
337 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
338 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
339 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
340 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
344 # Check no over-long lines in the input. (As a special exception this
345 # is permitted in verbatim sections or if the line contains a URL).
346 @lines = split /\n/, $content;
348 die "$progname: $input: line too long:\n$_\n"
350 substr ($_, 0, 1) ne ' ' &&
356 package Podwrapper
::Man
;
358 use vars
qw(@ISA $VERSION);
360 $VERSION = $package_version;
362 # Override the L<> method.
365 my ($self, $attrs, $text) = @_;
371 my $parser = Podwrapper
::Man
->new (
373 release
=> $release, section
=> $section,
376 stderr
=> 1, utf8
=> 1
379 $parser->no_errata_section (1);
380 $parser->complain_stderr (1);
381 $parser->output_string (\
$output);
382 $parser->parse_string_document ($content)
383 or die "$progname: could not parse input document";
384 open OUT
, ">$man" or die "$progname: $man: $!";
385 print OUT
$output or die "$progname: $man: $!";
386 close OUT
or die "$progname: $man: $!";
387 if ($parser->any_errata_seen) {
389 die "$input: errors or warnings in this POD file, see messages above\n"
391 #print "$progname: wrote $man\n";
396 # Subclass Pod::Simple::XHTML. See the documentation.
397 package Podwrapper
::XHTML
;
399 use vars
qw(@ISA $VERSION);
400 @ISA = qw(Pod::Simple::XHTML);
401 $VERSION = $package_version;
403 # Note this also allows links to related projects because they all
404 # appear together under the http://libguestfs.org website.
409 return 1 if /^Sys::Guestfs/;
410 return 0 if /^virt-install/;
411 return 1 if /^virt-/;
412 return 1 if /^libguestf/;
413 return 1 if /^guestf/;
414 return 1 if /^guestmount/;
415 return 1 if /^guestunmount/;
416 return 1 if /^hivex/;
417 return 1 if /^supermin/;
418 return 1 if /^libnbd/;
423 sub resolve_man_page_link
426 my $name = $_[0]; # eg. "nbdkit(1)", can be undef
427 my $anchor = $_[1]; # eg. "SYNOPSIS", can be undef
430 return $self->SUPER::resolve_man_page_link
(@_)
431 unless is_a_local_page
($name);
432 $name =~ s/\((.*)\)$/.$1/;
435 $r .= "#" . $self->idify ($anchor, 1) if defined $anchor;
439 # For some reason Pod::Simple::XHTML usually cannot find a
440 # title for the page. This defaults the HTML <title> field
441 # to the same as the man page name.
442 sub default_title
{ $name }
446 mkdir "$abs_top_builddir/html";
448 my $parser = Podwrapper
::XHTML
->new;
450 $parser->no_errata_section (1);
451 $parser->complain_stderr (1);
452 $parser->output_string (\
$output);
453 # Added in Pod::Simple 3.16, 2011-03-14.
454 eval { $parser->html_charset ("UTF-8") };
455 $parser->html_css ("pod.css");
457 $parser->parse_string_document ($content);
459 # Hack for Perl 5.16.
460 $output =~ s{/>pod.css<}{/>\n<};
462 open OUT
, ">$html" or die "$progname: $html: $!";
463 print OUT
$output or die "$progname: $html: $!";
464 close OUT
or die "$progname: $html: $!";
465 if ($parser->any_errata_seen) {
467 die "$input: errors or warnings in this POD file, see messages above\n"
469 #print "$progname: wrote $html\n";
474 my $parser = Pod
::Simple
::Text
->new;
476 $parser->no_errata_section (1);
477 $parser->complain_stderr (1);
478 $parser->output_string (\
$output);
479 $parser->parse_string_document ($content);
480 open OUT
, ">$text" or die "$progname: $text: $!";
481 binmode OUT
, ":utf8";
482 print OUT
$output or die "$progname: $text: $!";
483 close OUT
or die "$progname: $text: $!";
484 if ($parser->any_errata_seen) {
486 die "$input: errors or warnings in this POD file, see messages above\n"
488 #print "$progname: wrote $text\n";
496 open FILE
, "<:encoding(UTF-8)", $input or die "$progname: $input: $!";
502 sub read_verbatim_file
507 open FILE
, "<:encoding(UTF-8)", $input or die "$progname: $input: $!";
526 Copyright (C) 2012-2018 Red Hat Inc.