xref: /openbsd-src/gnu/usr.bin/perl/pod/buildtoc (revision 3d61058aa5c692477b6d18acfbbdb653a9930ff9)
1#!/usr/bin/perl -w
2
3use strict;
4use File::Spec;
5use FindBin;
6use Text::Wrap;
7use Getopt::Long;
8
9our $Quiet;
10no locale;
11
12# Assumption is that we're either already being run from the top level (*nix,
13# VMS), or have absolute paths in @INC (Win32, pod/Makefile)
14BEGIN {
15  my $Top = File::Spec->catdir($FindBin::Bin, File::Spec->updir);
16  chdir $Top or die "Can't chdir to $Top: $!";
17  require './Porting/pod_lib.pl';
18}
19
20die "$0: Usage: $0 [--quiet]\n"
21    unless GetOptions ('q|quiet' => \$Quiet) && !@ARGV;
22
23my $state = get_pod_metadata(0, sub { warn @_ if @_ }, 'pod/perltoc.pod');
24
25my $found = pods_to_install();
26
27my_die "Can't find any pods!\n" unless %$found;
28
29# Accumulating everything into a lexical before writing to disk dates from the
30# time when this script also provided the functionality of regen/pod_rules.pl
31# and this code was in a subroutine do_toc(). In turn, the use of a file scoped
32# lexical instead of a parameter or return value is because the code dates back
33# further still, and used *only* to create pod/perltoc.pod by printing direct
34
35my $OUT;
36my $roffitall;
37
38($_= <<"EOPOD2B") =~ s/^\t//gm and $OUT .= $_;
39
40	# !!!!!!!   DO NOT EDIT THIS FILE   !!!!!!!
41	# This file is autogenerated by buildtoc from all the other pods.
42	# Edit those files and run $0 to effect changes.
43
44	=encoding UTF-8
45
46	=head1 NAME
47
48	perltoc - perl documentation table of contents
49
50	=head1 DESCRIPTION
51
52	This page provides a brief table of contents for the rest of the Perl
53	documentation set.  It is meant to be scanned quickly or grepped
54	through to locate the proper section you're looking for.
55
56	=head1 BASIC DOCUMENTATION
57
58EOPOD2B
59
60# All the things in the master list that happen to be pod filenames
61foreach (grep {!$_->[2]{toc_omit}} @{$state->{master}}) {
62    $roffitall .= "    \$mandir/$_->[0].1 \\\n";
63    podset($_->[0], $_->[1]);
64}
65
66foreach my $type (qw(PRAGMA MODULE)) {
67    ($_= <<"EOPOD2B") =~ s/^\t//gm and $OUT .= $_;
68
69
70
71	=head1 $type DOCUMENTATION
72
73EOPOD2B
74
75    foreach my $name (sort keys %{$found->{$type}}) {
76        $roffitall .= "    \$libdir/$name.3 \\\n";
77        podset($name, $found->{$type}{$name});
78    }
79}
80
81$_= <<"EOPOD2B";
82
83
84	=head1 AUXILIARY DOCUMENTATION
85
86	Here should be listed all the extra programs' documentation, but they
87	don't all have manual pages yet:
88
89	=over 4
90
91EOPOD2B
92
93$_ .=  join "\n", map {"\t=item $_\n"} @{$state->{aux}};
94$_ .= <<"EOPOD2B" ;
95
96	=back
97
98	=head1 AUTHOR
99
100	Larry Wall <F<larry\@wall.org>>, with the help of oodles
101	of other folks.
102
103
104EOPOD2B
105
106s/^\t//gm;
107$OUT .= "$_\n";
108
109$OUT =~ s/\n\s+\n/\n\n/gs;
110$OUT =~ s/\n{3,}/\n\n/g;
111
112$OUT =~ s/([^\n]+)/wrap('', '', $1)/ge;
113
114write_or_die('pod/perltoc.pod', $OUT);
115
116write_or_die('pod/roffitall', <<'EOH' . $roffitall . <<'EOT');
117#!/bin/sh
118#
119# Usage: roffitall [-nroff|-psroff|-groff]
120#
121# Authors: Tom Christiansen, Raphael Manfredi
122
123me=roffitall
124tmp=.
125
126if test -f ../config.sh; then
127	. ../config.sh
128fi
129
130mandir=$installman1dir
131libdir=$installman3dir
132
133test -d $mandir || mandir=/usr/new/man/man1
134test -d $libdir || libdir=/usr/new/man/man3
135
136case "$1" in
137-nroff) cmd="nroff -man"; ext='txt';;
138-psroff) cmd="psroff -t"; ext='ps';;
139-groff) cmd="groff -man"; ext='ps';;
140*)
141	echo "Usage: roffitall [-nroff|-psroff|-groff]" >&2
142	exit 1
143	;;
144esac
145
146toroff=`
147	echo		\
148EOH
149    | perl -ne 'map { -r && print "$_ " } split'`
150
151    # Bypass internal shell buffer limit -- can't use case
152    if perl -e '$x = shift; exit($x =~ m|/|)' $toroff; then
153	echo "$me: empty file list -- did you run install?" >&2
154	exit 1
155    fi
156
157    #psroff -t -man -rC1 -rD1 -rF1 > $tmp/PerlDoc.ps 2>$tmp/PerlTOC.raw
158    #nroff -man -rC1 -rD1 -rF1 > $tmp/PerlDoc.txt 2>$tmp/PerlTOC.nr.raw
159
160    # First, create the raw data
161    run="$cmd -rC1 -rD1 -rF1 >$tmp/PerlDoc.$ext 2>$tmp/PerlTOC.$ext.raw"
162    echo "$me: running $run"
163    eval $run $toroff
164
165    #Now create the TOC
166    echo "$me: parsing TOC"
167    perl rofftoc $tmp/PerlTOC.$ext.raw > $tmp/PerlTOC.tmp.man
168    run="$cmd $tmp/PerlTOC.tmp.man >$tmp/PerlTOC.$ext"
169    echo "$me: running $run"
170    eval $run
171
172    # Finally, recreate the Doc, without the blank page 0
173    run="$cmd -rC1 -rD1 >$tmp/PerlDoc.$ext 2>$tmp/PerlTOC.$ext.raw"
174    echo "$me: running $run"
175    eval $run $toroff
176    rm -f $tmp/PerlTOC.tmp.man $tmp/PerlTOC.$ext.raw
177    echo "$me: leaving you with $tmp/PerlDoc.$ext and $tmp/PerlTOC.$ext"
178EOT
179
180exit(0);
181
182# Below are all the auxiliary routines for generating perltoc.pod
183
184my ($inhead1, $inhead2, $initem);
185
186sub podset {
187    my ($pod, $file) = @_;
188
189    open my $fh, '<:', $file or my_die "Can't open file '$file' for $pod: $!";
190
191    local *_;
192    my $found_pod;
193    while (<$fh>) {
194        if (/^=head1\s+NAME\b/) {
195            ++$found_pod;
196            last;
197        }
198    }
199
200    unless ($found_pod) {
201	warn "$0: NOTE: cannot find '=head1 NAME' in:\n  $file\n" unless $Quiet;
202        return;
203    }
204
205    seek $fh, 0, 0 or my_die "Can't rewind file '$file': $!";
206    local $/ = '';
207
208    while(<$fh>) {
209	s/\r$//;
210	if (s/^=head1 (NAME)\s*/=head2 /) {
211	    unhead1();
212	    $OUT .= "\n\n=head2 ";
213	    $_ = <$fh>;
214            last unless defined $_;
215	    # Remove svn keyword expansions from the Perl FAQ
216	    s/ \(\$Revision: \d+ \$\)//g;
217	    if ( /^\s*\Q$pod\E\b/ ) {
218		s/$pod\.pm/$pod/;       # '.pm' in NAME !?
219	    } else {
220		s/^/$pod, /;
221	    }
222	}
223	elsif (s/^=head1 (.*)/=item $1/) {
224	    unhead2();
225	    $OUT .= "=over 4\n\n" unless $inhead1;
226	    $inhead1 = 1;
227	    $_ .= "\n";
228	}
229	elsif (s/^=head2 (.*)/=item $1/) {
230	    unitem();
231	    $OUT .= "=over 4\n\n" unless $inhead2;
232	    $inhead2 = 1;
233	    $_ .= "\n";
234	}
235	elsif (s/^=item ([^=].*)/$1/) {
236	    next if $pod eq 'perldiag';
237	    s/^\s*\*\s*$// && next;
238	    s/^\s*\*\s*//;
239	    s/\n/ /g;
240	    s/\s+$//;
241	    # make sure inner links include the target page
242	    s{L<(?:[^|>]+\|)?\K/}{$pod/}g;
243	    next if /^[\d.]+$/;
244	    next if $pod eq 'perlmodlib' && /^ftp:/;
245	    $OUT .= ", " if $initem;
246	    $initem = 1;
247	    s/\.$//;
248	    s/^-X\b/-I<X>/;
249	}
250	else {
251	    unhead1() if /^=cut\s*\n/;
252	    next;
253	}
254	$OUT .= $_;
255    }
256}
257
258sub unhead1 {
259    unhead2();
260    if ($inhead1) {
261	$OUT .= "\n\n=back\n\n";
262    }
263    $inhead1 = 0;
264}
265
266sub unhead2 {
267    unitem();
268    if ($inhead2) {
269	$OUT .= "\n\n=back\n\n";
270    }
271    $inhead2 = 0;
272}
273
274sub unitem {
275    if ($initem) {
276	$OUT .= "\n\n";
277    }
278    $initem = 0;
279}
280
281=head1 NAME
282
283pod/buildtoc - Generate table of contents
284
285=head1 DESCRIPTION
286
287This program generates a table of contents for the documentation included in the Perl core distribution.  This table of contents takes two forms:
288
289=over 4
290
291=item 1 F<pod/perltoc.pod>
292
293A file in Perl's Plain Old Documentation (POD) format found in the F<pod/> directory in the core distribution.  Once Perl is installed, this file becomes accessible system-wide via C<perldoc perltoc>.
294
295=item 2 F<pod/roffitall>
296
297A shell script originally written by Tom Christiansen and Raphael Manfredi, also found in the F<pod/> directory, which can be used to translate Perl documentation into F<man> pages.
298
299=back
300
301=head1 USAGE
302
303This program will typically B<not> need to be called directly by a user.  Rather, it is one of the last commands invoked during C<make test_prep>:
304
305    ./perl -Ilib -I. -f pod/buildtoc -q
306
307The only command-line switch is C<-q|--quiet>, which quiets some non-critical warnings.
308
309=head2 Diagnosing Problems
310
311This program C<require>s F<Porting/pod_lib.pl> and makes use of several subroutines found in that file:  C<get_pod_metadata()> and C<pods_to_install()> in particular.  Consequently, any warnings or exceptions you see when this program is running may be being passed through from those subroutines.  You may have to (a) examine those subroutines and/or (b) run that program from the command-line to fully understand what is causing such warnings or exceptions.
312
313=head2 AUTHORS and MAINTENANCE
314
315This program was introduced into the Perl 5 core distribution by Andy Dougherty, based on earlier work by Tom Christiansen.  It is maintained by the Perl 5 Porters.
316
317=cut
318
319# ex: set ts=8 sts=4 sw=4 et:
320