This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
OS/2 and $^O updates, and first-pass general cleanup
[perl5.git] / utils / perldoc.PL
CommitLineData
4633a7c4
LW
1#!/usr/local/bin/perl
2
3use Config;
4use File::Basename qw(&basename &dirname);
5
85880f03 6# List explicitly here the variables you want Configure to
7# generate. Metaconfig only looks for shell variables, so you
8# have to mention them as if they were shell variables, not
9# %Config entries. Thus you write
4633a7c4 10# $startperl
85880f03 11# to ensure Configure will look for $Config{startperl}.
4633a7c4
LW
12
13# This forces PL files to create target in same directory as PL file.
14# This is so that make depend always knows where to find PL derivatives.
15chdir(dirname($0));
16($file = basename($0)) =~ s/\.PL$//;
17$file =~ s/\.pl$//
18 if ($Config{'osname'} eq 'VMS' or
19 $Config{'osname'} eq 'OS2'); # "case-forgiving"
20
21open OUT,">$file" or die "Can't create $file: $!";
22
23print "Extracting $file (with variable substitutions)\n";
24
25# In this section, perl variables will be expanded during extraction.
26# You can use $Config{...} to use Configure variables.
27
85880f03 28print OUT <<"!GROK!THIS!";
4633a7c4
LW
29$Config{'startperl'}
30 eval 'exec perl -S \$0 "\$@"'
31 if 0;
32!GROK!THIS!
33
34# In the following, perl variables are not expanded during extraction.
35
36print OUT <<'!NO!SUBS!';
85880f03 37 eval 'exec perl -S $0 "$@"'
38 if 0;
4633a7c4
LW
39
40#
41# Perldoc revision #1 -- look up a piece of documentation in .pod format that
42# is embedded in the perl installation tree.
43#
44# This is not to be confused with Tom Christianson's perlman, which is a
45# man replacement, written in perl. This perldoc is strictly for reading
46# the perl manuals, though it too is written in perl.
47#
85880f03 48# Version 1.11: Tue Dec 26 09:54:33 EST 1995
49# Kenneth Albanowski <kjahds@kjahds.com>
50# -added Charles Bailey's further VMS patches, and -u switch
51# -added -t switch, with pod2text support
52#
53# Version 1.10: Thu Nov 9 07:23:47 EST 1995
4633a7c4
LW
54# Kenneth Albanowski <kjahds@kjahds.com>
55# -added VMS support
56# -added better error recognition (on no found pages, just exit. On
57# missing nroff/pod2man, just display raw pod.)
58# -added recursive/case-insensitive matching (thanks, Andreas). This
59# slows things down a bit, unfortunately. Give a precise name, and
60# it'll run faster.
61#
62# Version 1.01: Tue May 30 14:47:34 EDT 1995
63# Andy Dougherty <doughera@lafcol.lafayette.edu>
64# -added pod documentation.
65# -added PATH searching.
66# -added searching pod/ subdirectory (mainly to pick up perlfunc.pod
67# and friends.
68#
69#
70# TODO:
71#
72# Cache directories read during sloppy match
73#
74
75=head1 NAME
76
77perldoc - Look up Perl documentation in pod format.
78
79=head1 SYNOPSIS
80
85880f03 81B<perldoc> [B<-h>] [B<-v>] [B<-t>] [B<-u>] PageName|ModuleName|ProgramName
4633a7c4
LW
82
83=head1 DESCRIPTION
84
85I<perldoc> looks up a piece of documentation in .pod format that is
86embedded in the perl installation tree or in a perl script, and displays
87it via pod2man | nroff -man | $PAGER. This is primarily used for the
88documentation for the perl library modules.
89
90Your system may also have man pages installed for those modules, in
91which case you can probably just use the man(1) command.
92
93=head1 OPTIONS
94
95=over 5
96
97=item B<-h> help
98
99Prints out a brief help message.
100
101=item B<-v> verbose
102
103Describes search for the item in detail.
104
85880f03 105=item B<-t> text output
106
107Display docs using plain text converter, instead of nroff. This may be faster,
108but it won't look as nice.
109
110=item B<-u> unformatted
111
112Find docs only; skip reformatting by pod2*
113
4633a7c4
LW
114=item B<PageName|ModuleName|ProgramName>
115
116The item you want to look up. Nested modules (such as C<File::Basename>)
117are specified either as C<File::Basename> or C<File/Basename>. You may also
118give a descriptive name of a page, such as C<perlfunc>. You make also give a
119partial or wrong-case name, such as "basename" for "File::Basename", but
120this will be slower, if there is more then one page with the same partial
121name, you will only get the first one.
122
123=back
124
125=head1 ENVIRONMENT
126
127Any switches in the C<PERLDOC> environment variable will be used before the
128command line arguments. C<perldoc> also searches directories
129specified by the C<PERL5LIB> (or C<PERLLIB> if C<PERL5LIB> is not
130defined) and C<PATH> environment variables.
131(The latter is so that embedded pods for executables, such as
132C<perldoc> itself, are available.)
133
134=head1 AUTHOR
135
136Kenneth Albanowski <kjahds@kjahds.com>
137
138Minor updates by Andy Dougherty <doughera@lafcol.lafayette.edu>
139
140=head1 SEE ALSO
141
142=head1 DIAGNOSTICS
143
144=cut
145
146if(@ARGV<1) {
147 die <<EOF;
85880f03 148Usage: $0 [-h] [-v] [-t] [-u] PageName|ModuleName|ProgramName
4633a7c4
LW
149
150We suggest you use "perldoc perldoc" to get aquainted
151with the system.
152EOF
153}
154
155use Getopt::Std;
85880f03 156use Config;
157$Is_VMS = $Config{'osname'} eq 'VMS';
4633a7c4
LW
158
159sub usage{
160 warn "@_\n" if @_;
161 die <<EOF;
85880f03 162perldoc [-h] [-v] [-u] PageName|ModuleName|ProgramName...
4633a7c4 163 -h Display this help message.
85880f03 164 -t Display pod using pod2text instead of pod2man and nroff.
165 -u Display unformatted pod text
4633a7c4
LW
166 -v Verbosely describe what's going on.
167PageName|ModuleName...
168 is the name of a piece of documentation that you want to look at. You
169 may either give a descriptive name of the page (as in the case of
170 `perlfunc') the name of a module, either like `Term::Info',
171 `Term/Info', the partial name of a module, like `info', or
172 `makemaker', or the name of a program, like `perldoc'.
173
174Any switches in the PERLDOC environment variable will be used before the
175command line arguments.
176
177EOF
178}
179
180use Text::ParseWords;
181
182
183unshift(@ARGV,shellwords($ENV{"PERLDOC"}));
184
85880f03 185getopts("htuv") || usage;
186
187usage if $opt_h || $opt_h; # avoid -w warning
4633a7c4 188
85880f03 189eval "use Pod::Text" if $opt_t;
4633a7c4 190
4633a7c4
LW
191@pages = @ARGV;
192
85880f03 193# VMS only -- use this hack until support for searchlist
194# logical names is better integrated into the Perl core
195sub translate_searchlist_logical {
196 my($lnm) = @_;
197 my($trans,@trans);
198 return unless $ENV{$lnm};
199 $trans = `show logical $lnm`;
200 $trans =~ s/\n1(.|\n)*//; # clip off iterative translations
201 @trans = split(/[\"=\s\n]+/,$trans); # break into words
202 splice(@trans,0,2); # pop off initial blank and orig name
203 @trans = grep(!/^\(/,@trans); # filter out table names
204 wantarray ? @trans : $trans[0];
205}
206
4633a7c4
LW
207sub containspod {
208 my($file) = @_;
209 local($_);
210 open(TEST,"<$file");
211 while(<TEST>) {
212 if(/^=head/) {
213 close(TEST);
214 return 1;
215 }
216 }
217 close(TEST);
218 return 0;
219}
220
221 sub minus_f_nocase {
222 my($file) = @_;
223 local *DIR;
224 local($")="/";
225 my(@p,$p,$cip);
226 foreach $p (split(/\//, $file)){
85880f03 227 if ($Is_VMS and not scalar @p) {
228 # VMS filesystems don't begin at '/'
229 push(@p,$p);
230 next;
231 }
4633a7c4
LW
232 if (-d ("@p/$p")){
233 push @p, $p;
234 } elsif (-f ("@p/$p")) {
235 return "@p/$p";
236 } else {
237 my $found=0;
238 my $lcp = lc $p;
239 opendir DIR, "@p";
240 while ($cip=readdir(DIR)) {
85880f03 241 $cip =~ s/\.dir$// if $Is_VMS;
4633a7c4
LW
242 if (lc $cip eq $lcp){
243 $found++;
244 last;
245 }
246 }
247 closedir DIR;
248 return "" unless $found;
249 push @p, $cip;
250 return "@p" if -f "@p";
251 }
252 }
253 return; # is not a file
254 }
255
256 sub searchfor {
257 my($recurse,$s,@dirs) = @_;
258 $s =~ s!::!/!g;
85880f03 259 $s = VMS::Filespec::unixify($s) if $Is_VMS;
4633a7c4
LW
260 printf STDERR "looking for $s in @dirs\n" if $opt_v;
261 my $ret;
262 my $i;
263 my $dir;
264 for ($i=0;$i<@dirs;$i++) {
265 $dir = $dirs[$i];
85880f03 266 ($dir = VMS::Filespec::unixpath($dir)) =~ s!/$!! if $Is_VMS;
4633a7c4
LW
267 if (( $ret = minus_f_nocase "$dir/$s.pod")
268 or ( $ret = minus_f_nocase "$dir/$s.pm" and containspod($ret))
269 or ( $ret = minus_f_nocase "$dir/$s" and containspod($ret))
85880f03 270 or ( $Is_VMS and
271 $ret = minus_f_nocase "$dir/$s.com" and containspod($ret))
4633a7c4
LW
272 or ( $ret = minus_f_nocase "$dir/pod/$s.pod")
273 or ( $ret = minus_f_nocase "$dir/pod/$s" and containspod($ret)))
274 { return $ret; }
275
276 if($recurse) {
277 opendir(D,$dir);
278 my(@newdirs) = grep(-d,map("$dir/$_",grep(!/^\.\.?$/,readdir(D))));
279 closedir(D);
85880f03 280 @newdirs = map((s/.dir$//,$_)[1],@newdirs) if $Is_VMS;
281 last unless @newdirs;
4633a7c4
LW
282 print STDERR "Also looking in @newdirs\n" if $opt_v;
283 push(@dirs,@newdirs);
284 }
285 }
286 return ();
287 }
288
289
290foreach (@pages) {
291 print STDERR "Searching for $_\n" if $opt_v;
292 # We must look both in @INC for library modules and in PATH
293 # for executables, like h2xs or perldoc itself.
294 @searchdirs = @INC;
85880f03 295 if ($Is_VMS) {
296 push(@searchdirs, translate_searchlist_logical('DCL$PATH'));
297 } else {
298 push(@searchdirs, grep(-d, split(':', $ENV{'PATH'})));
299 }
4633a7c4
LW
300 @files= searchfor(0,$_,@searchdirs);
301 if( @files ) {
302 print STDERR "Found as @files\n" if $opt_v;
303 } else {
304 # no match, try recursive search
305
306 @searchdirs = grep(!/^\.$/,@INC);
307
308
309 @files= searchfor(1,$_,@searchdirs);
310 if( @files ) {
85880f03 311 print STDERR "Loosely found as @files\n" if $opt_v;
4633a7c4
LW
312 } else {
313 print STDERR "No documentation found for '$_'\n";
314 }
315 }
316 push(@found,@files);
317}
318
319if(!@found) {
85880f03 320 exit ($Is_VMS ? 98962 : 1);
4633a7c4
LW
321}
322
4633a7c4
LW
323if( ! -t STDOUT ) { $opt_f = 1 }
324
85880f03 325unless($Is_VMS) {
4633a7c4 326 $tmp = "/tmp/perldoc1.$$";
4633a7c4 327 $goodresult = 0;
85880f03 328 @pagers = qw( more less pg view cat );
329 unshift(@pagers,$ENV{PAGER}) if $ENV{PAGER};
4633a7c4
LW
330} else {
331 $tmp = 'Sys$Scratch:perldoc.tmp1_'.$$;
85880f03 332 @pagers = qw( most more less type/page );
333 unshift(@pagers,$ENV{PERLDOC_PAGER}) if $ENV{PERLDOC_PAGER};
4633a7c4
LW
334 $goodresult = 1;
335}
336
337foreach (@found) {
338
85880f03 339 if($opt_t) {
340 open(TMP,">>$tmp");
341 Pod::Text::pod2text($_,*TMP);
342 close(TMP);
343 } elsif(not $opt_u) {
344 open(TMP,">>$tmp");
345 $rslt = `pod2man $_ | nroff -man`;
346 if ($Is_VMS) { $err = !($? % 2) || $rslt =~ /IVVERB/; }
347 else { $err = $?; }
348 print TMP $rslt unless $err;
349 close TMP;
350 }
4633a7c4 351
85880f03 352 if( $opt_u or $err or -z $tmp) {
4633a7c4
LW
353 open(OUT,">>$tmp");
354 open(IN,"<$_");
85880f03 355 $cut = 1;
356 while (<IN>) {
357 $cut = $1 eq 'cut' if /^=(\w+)/;
358 next if $cut;
359 print OUT;
360 }
4633a7c4
LW
361 close(IN);
362 close(OUT);
363 }
364}
365
366if( $opt_f ) {
367 open(TMP,"<$tmp");
368 print while <TMP>;
369 close(TMP);
370} else {
85880f03 371 foreach $pager (@pagers) {
372 $sts = system("$pager $tmp");
373 last if $Is_VMS && ($sts & 1);
374 last unless $sts;
4633a7c4
LW
375 }
376}
377
3781 while unlink($tmp); #Possibly pointless VMSism
379
380exit 0;
381!NO!SUBS!
382
383close OUT or die "Can't close $file: $!";
384chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
385exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';