[inseparable changes from patch from perl-5.003_97d to perl-5.003_97e]
[p5sagit/p5-mst-13.2.git] / utils / perldoc.PL
1 #!/usr/local/bin/perl
2
3 use Config;
4 use File::Basename qw(&basename &dirname);
5
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
10 #  $startperl
11 # to ensure Configure will look for $Config{startperl}.
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.
15 chdir dirname($0);
16 $file = basename($0, '.PL');
17 $file .= '.com' if $^O eq 'VMS';
18
19 open OUT,">$file" or die "Can't create $file: $!";
20
21 print "Extracting $file (with variable substitutions)\n";
22
23 # In this section, perl variables will be expanded during extraction.
24 # You can use $Config{...} to use Configure variables.
25
26 print OUT <<"!GROK!THIS!";
27 $Config{startperl}
28     eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
29         if \$running_under_some_shell;
30
31 \@pagers = ();
32 push \@pagers, "$Config{'pager'}" if -x "$Config{'pager'}";
33 !GROK!THIS!
34
35 # In the following, perl variables are not expanded during extraction.
36
37 print OUT <<'!NO!SUBS!';
38
39 #
40 # Perldoc revision #1 -- look up a piece of documentation in .pod format that
41 # is embedded in the perl installation tree.
42 #
43 # This is not to be confused with Tom Christianson's perlman, which is a
44 # man replacement, written in perl. This perldoc is strictly for reading
45 # the perl manuals, though it too is written in perl.
46
47 if(@ARGV<1) {
48         $0 =~ s,.*/,,;
49         die <<EOF;
50 Usage: $0 [-h] [-v] [-t] [-u] [-m] [-l] PageName|ModuleName|ProgramName
51        $0 -f PerlFunc
52
53 We suggest you use "perldoc perldoc" to get aquainted 
54 with the system.
55 EOF
56 }
57
58 use Getopt::Std;
59 $Is_VMS = $^O eq 'VMS';
60 $Is_MSWin32 = $^O eq 'MSWin32';
61
62 sub usage{
63     warn "@_\n" if @_;
64     # Erase evidence of previous errors (if any), so exit status is simple.
65     $! = 0;
66     die <<EOF;
67 perldoc [options] PageName|ModuleName|ProgramName...
68 perldoc [options] -f BuiltinFunction
69
70 Options:
71     -h   Display this help message
72     -t   Display pod using pod2text instead of pod2man and nroff
73              (-t is the default on win32)
74     -u   Display unformatted pod text
75     -m   Display modules file in its entirety
76     -l   Display the modules file name
77     -v   Verbosely describe what's going on
78
79 PageName|ModuleName...
80          is the name of a piece of documentation that you want to look at. You 
81          may either give a descriptive name of the page (as in the case of
82          `perlfunc') the name of a module, either like `Term::Info', 
83          `Term/Info', the partial name of a module, like `info', or 
84          `makemaker', or the name of a program, like `perldoc'.
85
86 BuiltinFunction
87          is the name of a perl function.  Will extract documentation from
88          `perlfunc'.
89          
90 Any switches in the PERLDOC environment variable will be used before the 
91 command line arguments.
92
93 EOF
94 }
95
96 use Text::ParseWords;
97
98
99 unshift(@ARGV,shellwords($ENV{"PERLDOC"}));
100
101 getopts("mhtluvf:") || usage;
102
103 usage if $opt_h || $opt_h; # avoid -w warning
104
105 if ($opt_t + $opt_u + $opt_m + $opt_l > 1) {
106     usage("only one of -t, -u, -m or -l")
107 } elsif ($Is_MSWin32) {
108     $opt_t = 1 unless $opt_t + $opt_u + $opt_m + $opt_l;
109 }
110
111 if ($opt_t) { require Pod::Text; import Pod::Text; }
112
113 if ($opt_f) {
114    @pages = ("perlfunc");
115 } else {
116    @pages = @ARGV;
117 }
118
119
120
121 sub containspod {
122         my($file) = @_;
123         local($_);
124         open(TEST,"<$file");
125         while(<TEST>) {
126                 if(/^=head/) {
127                         close(TEST);
128                         return 1;
129                 }
130         }
131         close(TEST);
132         return 0;
133 }
134
135  sub minus_f_nocase {
136      my($file) = @_;
137      local *DIR;
138      local($")="/";
139      my(@p,$p,$cip);
140      foreach $p (split(/\//, $file)){
141         if (($Is_VMS or $Is_MSWin32 or $^O eq 'os2') and not scalar @p) {
142             # VMSish filesystems don't begin at '/'
143             push(@p,$p);
144             next;
145         }
146         if (-d ("@p/$p")){
147             push @p, $p;
148         } elsif (-f ("@p/$p")) {
149             return "@p/$p";
150         } else {
151             my $found=0;
152             my $lcp = lc $p;
153             opendir DIR, "@p";
154             while ($cip=readdir(DIR)) {
155                 $cip =~ s/\.dir$// if $Is_VMS;
156                 if (lc $cip eq $lcp){
157                     $found++;
158                     last;
159                 }
160             }
161             closedir DIR;
162             return "" unless $found;
163             push @p, $cip;
164             return "@p" if -f "@p";
165         }
166      }
167      return; # is not a file
168  }
169  
170   sub searchfor {
171         my($recurse,$s,@dirs) = @_;
172         $s =~ s!::!/!g;
173         $s = VMS::Filespec::unixify($s) if $Is_VMS;
174         return $s if -f $s && containspod($s);
175         printf STDERR "looking for $s in @dirs\n" if $opt_v;
176         my $ret;
177         my $i;
178         my $dir;
179         for ($i=0;$i<@dirs;$i++) {
180                 $dir = $dirs[$i];
181                 ($dir = VMS::Filespec::unixpath($dir)) =~ s!/$!! if $Is_VMS;
182             if ((    $ret = minus_f_nocase "$dir/$s.pod")
183                 or ( $ret = minus_f_nocase "$dir/$s.pm"  and containspod($ret))
184                 or ( $ret = minus_f_nocase "$dir/$s"     and containspod($ret))
185                 or ( $Is_VMS and 
186                      $ret = minus_f_nocase "$dir/$s.com" and containspod($ret))
187                 or ( $Is_MSWin32 and 
188                      $ret = minus_f_nocase "$dir/$s.bat" and containspod($ret))
189                 or ( $ret = minus_f_nocase "$dir/pod/$s.pod")
190                 or ( $ret = minus_f_nocase "$dir/pod/$s" and containspod($ret)))
191                 { return $ret; }
192                 
193                 if($recurse) {
194                         opendir(D,$dir);
195                         my(@newdirs) = grep(-d,map("$dir/$_",grep(!/^\.\.?$/,readdir(D))));
196                         closedir(D);
197                         @newdirs = map((s/.dir$//,$_)[1],@newdirs) if $Is_VMS;
198                         next unless @newdirs;
199                         print STDERR "Also looking in @newdirs\n" if $opt_v;
200                         push(@dirs,@newdirs);
201                 }
202         }
203         return ();
204   }
205
206
207 foreach (@pages) {
208         print STDERR "Searching for $_\n" if $opt_v;
209         # We must look both in @INC for library modules and in PATH
210         # for executables, like h2xs or perldoc itself.
211         @searchdirs = @INC;
212         unless ($opt_m) { 
213             if ($Is_VMS) {
214                 my($i,$trn);
215                 for ($i = 0; $trn = $ENV{'DCL$PATH'.$i}; $i++) {
216                     push(@searchdirs,$trn);
217                 }
218             } elsif ($Is_MSWin32) {
219                 push(@searchdirs, grep(-d, split(';', $ENV{'PATH'})));
220             } else {
221                     push(@searchdirs, grep(-d, split(':', $ENV{'PATH'})));
222             }
223             @files= searchfor(0,$_,@searchdirs);
224         }
225         if( @files ) {
226                 print STDERR "Found as @files\n" if $opt_v;
227         } else {
228                 # no match, try recursive search
229                 
230                 @searchdirs = grep(!/^\.$/,@INC);
231                 
232                 
233                 @files= searchfor(1,$_,@searchdirs);
234                 if( @files ) {
235                         print STDERR "Loosely found as @files\n" if $opt_v;
236                 } else {
237                         print STDERR "No documentation found for '$_'\n";
238                 }
239         }
240         push(@found,@files);
241 }
242
243 if(!@found) {
244         exit ($Is_VMS ? 98962 : 1);
245 }
246
247 if ($opt_l) {
248     print join("\n", @found), "\n";
249     exit;
250 }
251
252 if( ! -t STDOUT ) { $no_tty = 1 }
253
254 if ($Is_MSWin32) {
255         $tmp = "$ENV{TEMP}\\perldoc1.$$";
256         push @pagers, qw( more< less notepad );
257         unshift @pagers, $ENV{PAGER}  if $ENV{PAGER};
258 } elsif ($Is_VMS) {
259         $tmp = 'Sys$Scratch:perldoc.tmp1_'.$$;
260         push @pagers, qw( most more less type/page );
261 } else {
262         $tmp = "/tmp/perldoc1.$$";
263         push @pagers, qw( more less pg view cat );
264         unshift @pagers, $ENV{PAGER}  if $ENV{PAGER};
265 }
266 unshift @pagers, $ENV{PERLDOC_PAGER} if $ENV{PERLDOC_PAGER};
267
268 if ($opt_m) {
269         foreach $pager (@pagers) {
270                 system("$pager @found") or exit;
271         }
272         if ($Is_VMS) { eval 'use vmsish qw(status exit); exit $?' }
273         exit 1;
274
275
276 if ($opt_f) {
277    my $perlfunc = shift @found;
278    open(PFUNC, $perlfunc) or die "Can't open $perlfunc: $!";
279
280    # Skip introduction
281    while (<PFUNC>) {
282        last if /^=head2 Alphabetical Listing of Perl Functions/;
283    }
284
285    # Look for our function
286    my $found = 0;
287    while (<PFUNC>) {
288        if (/^=item\s+\Q$opt_f\E\b/o)  {
289            $found++;
290        } elsif (/^=item/) {
291            last if $found;
292        }
293        push(@pod, $_) if $found;
294    }
295    if (@pod) {
296        if ($opt_t) {
297            open(FORMATTER, "| pod2text") || die "Can't start filter";
298            print FORMATTER "=over 8\n\n";
299            print FORMATTER @pod;
300            print FORMATTER "=back\n";
301            close(FORMATTER);
302        } else {
303            print @pod;
304        }
305    } else {
306        die "No documentation for perl function `$opt_f' found\n";
307    }
308    exit;
309 }
310
311 foreach (@found) {
312
313         if($opt_t) {
314                 open(TMP,">>$tmp");
315                 Pod::Text::pod2text($_,*TMP);
316                 close(TMP);
317         } elsif(not $opt_u) {
318                 my $cmd = "pod2man --lax $_ | nroff -man";
319                 $cmd .= " | col -x" if $^O =~ /hpux/;
320                 $rslt = `$cmd`;
321                 unless(($err = $?)) {
322                         open(TMP,">>$tmp");
323                         print TMP $rslt;
324                         close TMP;
325                 }
326         }
327                                                         
328         if( $opt_u or $err or -z $tmp) {
329                 open(OUT,">>$tmp");
330                 open(IN,"<$_");
331                 $cut = 1;
332                 while (<IN>) {
333                         $cut = $1 eq 'cut' if /^=(\w+)/;
334                         next if $cut;
335                         print OUT;
336                 }
337                 close(IN);
338                 close(OUT);
339         }
340 }
341
342 if( $no_tty ) {
343         open(TMP,"<$tmp");
344         print while <TMP>;
345         close(TMP);
346 } else {
347         foreach $pager (@pagers) {
348                 system("$pager $tmp") or last;
349         }
350 }
351
352 1 while unlink($tmp); #Possibly pointless VMSism
353
354 exit 0;
355
356 __END__
357
358 =head1 NAME
359
360 perldoc - Look up Perl documentation in pod format.
361
362 =head1 SYNOPSIS
363
364 B<perldoc> [B<-h>] [B<-v>] [B<-t>] [B<-u>] [B<-m>] [B<-l>] PageName|ModuleName|ProgramName
365
366 B<perldoc> B<-f> BuiltinFunction
367
368 =head1 DESCRIPTION
369
370 I<perldoc> looks up a piece of documentation in .pod format that is embedded
371 in the perl installation tree or in a perl script, and displays it via
372 C<pod2man | nroff -man | $PAGER>. (In addition, if running under HP-UX,
373 C<col -x> will be used.) This is primarily used for the documentation for
374 the perl library modules.
375
376 Your system may also have man pages installed for those modules, in
377 which case you can probably just use the man(1) command.
378
379 =head1 OPTIONS
380
381 =over 5
382
383 =item B<-h> help
384
385 Prints out a brief help message.
386
387 =item B<-v> verbose
388
389 Describes search for the item in detail.
390
391 =item B<-t> text output
392
393 Display docs using plain text converter, instead of nroff. This may be faster,
394 but it won't look as nice.
395
396 =item B<-u> unformatted
397
398 Find docs only; skip reformatting by pod2*
399
400 =item B<-m> module
401
402 Display the entire module: both code and unformatted pod documentation.
403 This may be useful if the docs don't explain a function in the detail
404 you need, and you'd like to inspect the code directly; perldoc will find
405 the file for you and simply hand it off for display.
406
407 =item B<-l> file name only
408
409 Display the file name of the module found.
410
411 =item B<-f> perlfunc
412
413 The B<-f> option followed by the name of a perl built in function will
414 extract the documentation of this function from L<perlfunc>.
415
416 =item B<PageName|ModuleName|ProgramName>
417
418 The item you want to look up.  Nested modules (such as C<File::Basename>)
419 are specified either as C<File::Basename> or C<File/Basename>.  You may also
420 give a descriptive name of a page, such as C<perlfunc>. You make also give a
421 partial or wrong-case name, such as "basename" for "File::Basename", but
422 this will be slower, if there is more then one page with the same partial
423 name, you will only get the first one.
424
425 =back
426
427 =head1 ENVIRONMENT
428
429 Any switches in the C<PERLDOC> environment variable will be used before the 
430 command line arguments.  C<perldoc> also searches directories
431 specified by the C<PERL5LIB> (or C<PERLLIB> if C<PERL5LIB> is not
432 defined) and C<PATH> environment variables.
433 (The latter is so that embedded pods for executables, such as
434 C<perldoc> itself, are available.)
435
436 =head1 AUTHOR
437
438 Kenneth Albanowski <kjahds@kjahds.com>
439
440 Minor updates by Andy Dougherty <doughera@lafcol.lafayette.edu>
441
442 =cut
443
444 #
445 # Version 1.12: Sat Apr 12 22:41:09 EST 1997
446 #       Gurusamy Sarathy <gsar@umich.edu>
447 #       -various fixes for win32
448 # Version 1.11: Tue Dec 26 09:54:33 EST 1995
449 #       Kenneth Albanowski <kjahds@kjahds.com>
450 #   -added Charles Bailey's further VMS patches, and -u switch
451 #   -added -t switch, with pod2text support
452
453 # Version 1.10: Thu Nov  9 07:23:47 EST 1995
454 #               Kenneth Albanowski <kjahds@kjahds.com>
455 #       -added VMS support
456 #       -added better error recognition (on no found pages, just exit. On
457 #        missing nroff/pod2man, just display raw pod.)
458 #       -added recursive/case-insensitive matching (thanks, Andreas). This
459 #        slows things down a bit, unfortunately. Give a precise name, and
460 #        it'll run faster.
461 #
462 # Version 1.01: Tue May 30 14:47:34 EDT 1995
463 #               Andy Dougherty  <doughera@lafcol.lafayette.edu>
464 #   -added pod documentation.
465 #   -added PATH searching.
466 #   -added searching pod/ subdirectory (mainly to pick up perlfunc.pod
467 #    and friends.
468 #
469 #
470 # TODO:
471 #
472 #       Cache directories read during sloppy match
473 !NO!SUBS!
474
475 close OUT or die "Can't close $file: $!";
476 chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
477 exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';