3 use 5.006; # we use some open(X, "<", $y) syntax
9 use Fcntl; # for sysopen
10 use File::Spec::Functions qw(catfile catdir splitdir);
12 use vars qw($VERSION @Pagers $Bindir $Pod2man
13 $Temp_Files_Created $Temp_File_Lifetime
16 #..........................................................................
18 BEGIN { # Make a DEBUG constant very first thing...
19 unless(defined &DEBUG) {
20 if(($ENV{'PERLDOCDEBUG'} || '') =~ m/^(\d+)/) { # untaint
21 eval("sub DEBUG () {$1}");
22 die "WHAT? Couldn't eval-up a DEBUG constant!? $@" if $@;
29 use Pod::Perldoc::GetOptsOO; # uses the DEBUG.
31 #..........................................................................
37 *IS_VMS = $^O eq 'VMS' ? \&TRUE : \&FALSE unless defined &IS_VMS;
38 *IS_MSWin32 = $^O eq 'MSWin32' ? \&TRUE : \&FALSE unless defined &IS_MSWin32;
39 *IS_Dos = $^O eq 'dos' ? \&TRUE : \&FALSE unless defined &IS_Dos;
40 *IS_OS2 = $^O eq 'os2' ? \&TRUE : \&FALSE unless defined &IS_OS2;
41 *IS_Cygwin = $^O eq 'cygwin' ? \&TRUE : \&FALSE unless defined &IS_Cygwin;
42 *IS_Linux = $^O eq 'linux' ? \&TRUE : \&FALSE unless defined &IS_Linux;
43 *IS_HPUX = $^O =~ m/hpux/ ? \&TRUE : \&FALSE unless defined &IS_HPUX;
46 $Temp_File_Lifetime ||= 60 * 60 * 24 * 5;
47 # If it's older than five days, it's quite unlikely
48 # that anyone's still looking at it!!
49 # (Currently used only by the MSWin cleanup routine)
52 #..........................................................................
53 { my $pager = $Config{'pager'};
54 push @Pagers, $pager if -x (split /\s+/, $pager)[0] or IS_VMS;
56 $Bindir = $Config{'scriptdirexp'};
57 $Pod2man = "pod2man" . ( $Config{'versiononly'} ? $Config{'version'} : '' );
59 # End of class-init stuff
61 ###########################################################################
65 foreach my $subname (map "opt_$_", split '', q{mhlvriFfXqnTdUL}) {
67 *$subname = do{ use strict 'refs'; sub () { shift->_elem($subname, @_) } };
70 # And these are so that GetOptsOO knows they take options:
71 sub opt_f_with { shift->_elem('opt_f', @_) }
72 sub opt_q_with { shift->_elem('opt_q', @_) }
73 sub opt_d_with { shift->_elem('opt_d', @_) }
74 sub opt_L_with { shift->_elem('opt_L', @_) }
76 sub opt_w_with { # Specify an option for the formatter subclass
77 my($self, $value) = @_;
78 if($value =~ m/^([-_a-zA-Z][-_a-zA-Z0-9]*)(?:[=\:](.*?))?$/s) {
80 my $option_value = defined($2) ? $2 : "TRUE";
81 $option =~ tr/\-/_/s; # tolerate "foo-bar" for "foo_bar"
82 $self->add_formatter_option( $option, $option_value );
84 warn "\"$value\" isn't a good formatter option name. I'm ignoring it!\n";
89 sub opt_M_with { # specify formatter class name(s)
90 my($self, $classes) = @_;
91 return unless defined $classes and length $classes;
92 DEBUG > 4 and print "Considering new formatter classes -M$classes\n";
94 foreach my $classname (split m/[,;]+/s, $classes) {
95 next unless $classname =~ m/\S/;
96 if( $classname =~ m/^(\w+(::\w+)+)$/s ) {
97 # A mildly restrictive concept of what modulenames are valid.
98 push @classes_to_add, $1; # untaint
100 warn "\"$classname\" isn't a valid classname. Ignoring.\n";
104 unshift @{ $self->{'formatter_classes'} }, @classes_to_add;
107 "Adding @classes_to_add to the list of formatter classes, "
108 . "making them @{ $self->{'formatter_classes'} }.\n"
114 sub opt_V { # report version and exit
116 "Perldoc v$VERSION, under perl v$] for $^O",
118 (defined(&Win32::BuildNumber) and defined &Win32::BuildNumber())
119 ? (" (win32 build ", &Win32::BuildNumber(), ")") : (),
121 (chr(65) eq 'A') ? () : " (non-ASCII)",
128 sub opt_t { # choose plaintext as output format
130 $self->opt_o_with('text') if @_ and $_[0];
131 return $self->_elem('opt_t', @_);
134 sub opt_u { # choose raw pod as output format
136 $self->opt_o_with('pod') if @_ and $_[0];
137 return $self->_elem('opt_u', @_);
141 # choose man as the output format, and specify the proggy to run
143 $self->opt_o_with('man') if @_ and $_[0];
144 $self->_elem('opt_n', @_);
147 sub opt_o_with { # "o" for output format
148 my($self, $rest) = @_;
149 return unless defined $rest and length $rest;
150 if($rest =~ m/^(\w+)$/s) {
153 warn "\"$rest\" isn't a valid output format. Skipping.\n";
157 $self->aside("Noting \"$rest\" as desired output format...\n");
159 # Figure out what class(es) that could actually mean...
162 foreach my $prefix ("Pod::Perldoc::To", "Pod::Simple::", "Pod::") {
165 $rest, # Yes, try it first with the given capitalization
166 "\L$rest", "\L\u$rest", "\U$rest" # And then try variations
169 push @classes, $prefix . $stem;
170 #print "Considering $prefix$stem\n";
173 # Tidier, but misses too much:
174 #push @classes, $prefix . ucfirst(lc($rest));
176 $self->opt_M_with( join ";", @classes );
180 ###########################################################################
181 # % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
183 sub run { # to be called by the "perldoc" executable
186 print "Parameters to $class\->run:\n";
189 $x[1] = '<undef>' unless defined $x[1];
190 $x[1] = "@{$x[1]}" if ref( $x[1] ) eq 'ARRAY';
191 print " [$x[0]] => [$x[1]]\n";
196 return $class -> new(@_) -> process() || 0;
199 # % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
200 ###########################################################################
202 sub new { # yeah, nothing fancy
204 my $new = bless {@_}, (ref($class) || $class);
205 DEBUG > 1 and print "New $class object $new\n";
210 #..........................................................................
212 sub aside { # If we're in -v or DEBUG mode, say this.
214 if( DEBUG or $self->opt_v ) {
217 my $callsub = (caller(1))[3];
218 my $package = quotemeta(__PACKAGE__ . '::');
219 $callsub =~ s/^$package/'/os;
220 # the o is justified, as $package really won't change.
225 if(DEBUG) { print $out } else { print STDERR $out }
230 #..........................................................................
236 # Erase evidence of previous errors (if any), so exit status is simple.
240 perldoc [options] PageName|ModuleName|ProgramName...
241 perldoc [options] -f BuiltinFunction
242 perldoc [options] -q FAQRegex
245 -h Display this help message
247 -r Recursive search (slow)
249 -t Display pod using pod2text instead of pod2man and nroff
250 (-t is the default on win32 unless -n is specified)
251 -u Display unformatted pod text
252 -m Display module's file in its entirety
253 -n Specify replacement for nroff
254 -l Display the module's file name
255 -F Arguments are file names, not modules
256 -v Verbosely describe what's going on
257 -T Send output to STDOUT without any pager
258 -d output_filename_to_send_to
259 -o output_format_name
260 -M FormatterModuleNameToUse
261 -w formatter_option:option_value
262 -L translation_code Choose doc translation (if any)
263 -X use index if present (looks for pod.idx at $Config{archlib})
264 -q Search the text of questions (not answers) in perlfaq[1-9]
266 PageName|ModuleName...
267 is the name of a piece of documentation that you want to look at. You
268 may either give a descriptive name of the page (as in the case of
269 `perlfunc') the name of a module, either like `Term::Info' or like
270 `Term/Info', or the name of a program, like `perldoc'.
273 is the name of a perl function. Will extract documentation from
277 is a regex. Will search perlfaq[1-9] for and extract any
278 questions that match.
280 Any switches in the PERLDOC environment variable will be used before the
281 command line arguments. The optional pod index file contains a list of
282 filenames, one per line.
288 #..........................................................................
291 my $me = $0; # Editing $0 is unportable
293 $me =~ s,.*[/\\],,; # get basename
296 Usage: $me [-h] [-V] [-r] [-i] [-v] [-t] [-u] [-m] [-n nroffer_program] [-l] [-T] [-d output_filename] [-o output_format] [-M FormatterModuleNameToUse] [-w formatter_option:option_value] [-L translation_code] [-F] [-X] PageName|ModuleName|ProgramName
300 The -h option prints more help. Also try "perldoc perldoc" to get
301 acquainted with the system. [Perldoc v$VERSION]
306 #..........................................................................
308 sub pagers { @{ shift->{'pagers'} } }
310 #..........................................................................
312 sub _elem { # handy scalar meta-accessor: shift->_elem("foo", @_)
313 if(@_ > 2) { return $_[0]{ $_[1] } = $_[2] }
314 else { return $_[0]{ $_[1] } }
316 #..........................................................................
317 ###########################################################################
319 # Init formatter switches, and start it off with __bindir and all that
320 # other stuff that ToMan.pm needs.
326 # Make sure creat()s are neither too much nor too little
327 eval { umask(0077) }; # doubtless someone has no mask
329 $self->{'args'} ||= \@ARGV;
330 $self->{'found'} ||= [];
331 $self->{'temp_file_list'} ||= [];
334 $self->{'target'} = undef;
336 $self->init_formatter_class_list;
338 $self->{'pagers' } = [@Pagers] unless exists $self->{'pagers'};
339 $self->{'bindir' } = $Bindir unless exists $self->{'bindir'};
340 $self->{'pod2man'} = $Pod2man unless exists $self->{'pod2man'};
342 push @{ $self->{'formatter_switches'} = [] }, (
343 # Yeah, we could use a hashref, but maybe there's some class where options
344 # have to be ordered; so we'll use an arrayref.
346 [ '__bindir' => $self->{'bindir' } ],
347 [ '__pod2man' => $self->{'pod2man'} ],
350 DEBUG > 3 and printf "Formatter switches now: [%s]\n",
351 join ' ', map "[@$_]", @{ $self->{'formatter_switches'} };
353 $self->{'translators'} = [];
354 $self->{'extra_search_dirs'} = [];
359 #..........................................................................
361 sub init_formatter_class_list {
363 $self->{'formatter_classes'} ||= [];
365 # Remember, no switches have been read yet, when
366 # we've started this routine.
368 $self->opt_M_with('Pod::Perldoc::ToPod'); # the always-there fallthru
369 $self->opt_o_with('text');
370 $self->opt_o_with('man') unless IS_MSWin32 || IS_Dos
372 ($ENV{TERM} || '') !~ /dumb|emacs|none|unknown/i
378 #..........................................................................
381 # if this ever returns, its retval will be used for exit(RETVAL)
384 DEBUG > 1 and print " Beginning process.\n";
385 DEBUG > 1 and print " Args: @{$self->{'args'}}\n\n";
387 print "Object contents:\n";
390 $x[1] = '<undef>' unless defined $x[1];
391 $x[1] = "@{$x[1]}" if ref( $x[1] ) eq 'ARRAY';
392 print " [$x[0]] => [$x[1]]\n";
398 # TODO: make it deal with being invoked as various different things
401 return $self->usage_brief unless @{ $self->{'args'} };
402 $self->pagers_guessing;
403 $self->options_reading;
404 $self->aside(sprintf "$0 => %s v%s\n", ref($self), $self->VERSION);
405 $self->drop_privs_maybe;
406 $self->options_processing;
408 # Hm, we have @pages and @found, but we only really act on one
409 # file per call, with the exception of the opt_q hack, and with
415 $self->{'pages'} = \@pages;
416 if( $self->opt_f) { @pages = ("perlfunc") }
417 elsif( $self->opt_q) { @pages = ("perlfaq1" .. "perlfaq9") }
418 else { @pages = @{$self->{'args'}};
420 # if @pages == 1 and $pages[0] eq 'perldoc';
423 return $self->usage_brief unless @pages;
425 $self->find_good_formatter_class();
426 $self->formatter_sanity_check();
428 $self->maybe_diddle_INC();
429 # for when we're apparently in a module or extension directory
431 my @found = $self->grand_search_init(\@pages);
432 exit (IS_VMS ? 98962 : 1) unless @found;
435 DEBUG and print "We're in -l mode, so byebye after this:\n";
436 print join("\n", @found), "\n";
440 $self->tweak_found_pathnames(\@found);
441 $self->assert_closing_stdout;
442 return $self->page_module_file(@found) if $self->opt_m;
443 DEBUG > 2 and print "Found: [@found]\n";
445 return $self->render_and_page(\@found);
448 #..........................................................................
451 my( %class_seen, %class_loaded );
452 sub find_good_formatter_class {
454 my @class_list = @{ $self->{'formatter_classes'} || [] };
455 die "WHAT? Nothing in the formatter class list!?" unless @class_list;
457 my $good_class_found;
458 foreach my $c (@class_list) {
459 DEBUG > 4 and print "Trying to load $c...\n";
460 if($class_loaded{$c}) {
461 DEBUG > 4 and print "OK, the already-loaded $c it is!\n";
462 $good_class_found = $c;
466 if($class_seen{$c}) {
468 "I've tried $c before, and it's no good. Skipping.\n";
474 if( $c->can('parse_from_file') ) {
476 "Interesting, the formatter class $c is already loaded!\n";
479 (IS_VMS or IS_MSWin32 or IS_Dos or IS_OS2)
480 # the alway case-insensitive fs's
481 and $class_seen{lc("~$c")}++
484 "We already used something quite like \"\L$c\E\", so no point using $c\n";
485 # This avoids redefining the package.
487 DEBUG > 4 and print "Trying to eval 'require $c'...\n";
490 if(DEBUG() or $self->opt_v) {
491 # feh, let 'em see it
494 # The average user just has no reason to be seeing
495 # $^W-suppressable warnings from the the require!
500 DEBUG > 4 and print "Couldn't load $c: $!\n";
505 if( $c->can('parse_from_file') ) {
506 DEBUG > 4 and print "Settling on $c\n";
508 $v = ( defined $v and length $v ) ? " version $v" : '';
509 $self->aside("Formatter class $c$v successfully loaded!\n");
510 $good_class_found = $c;
513 DEBUG > 4 and print "Class $c isn't a formatter?! Skipping.\n";
517 die "Can't find any loadable formatter class in @class_list?!\nAborting"
518 unless $good_class_found;
520 $self->{'formatter_class'} = $good_class_found;
521 $self->aside("Will format with the class $good_class_found\n");
527 #..........................................................................
529 sub formatter_sanity_check {
531 my $formatter_class = $self->{'formatter_class'}
532 || die "NO FORMATTER CLASS YET!?";
534 if(!$self->opt_T # so -T can FORCE sending to STDOUT
535 and $formatter_class->can('is_pageable')
536 and !$formatter_class->is_pageable
537 and !$formatter_class->can('page_for_perldoc')
540 ($formatter_class->can('output_extension')
541 && $formatter_class->output_extension
543 $ext = ".$ext" if length $ext;
546 "When using Perldoc to format with $formatter_class, you have to\n"
547 . "specify -T or -dsomefile$ext\n"
548 . "See `perldoc perldoc' for more information on those switches.\n"
553 #..........................................................................
555 sub render_and_page {
556 my($self, $found_list) = @_;
558 $self->maybe_generate_dynamic_pod($found_list);
560 my($out, $formatter) = $self->render_findings($found_list);
563 printf "Perldoc (%s) output saved to %s\n",
564 $self->{'formatter_class'} || ref($self),
566 print "But notice that it's 0 bytes long!\n" unless -s $out;
569 } elsif( # Allow the formatter to "page" itself, if it wants.
570 $formatter->can('page_for_perldoc')
572 $self->aside("Going to call $formatter\->page_for_perldoc(\"$out\")\n");
573 if( $formatter->page_for_perldoc($out, $self) ) {
574 $self->aside("page_for_perldoc returned true, so NOT paging with $self.\n");
577 $self->aside("page_for_perldoc returned false, so paging with $self instead.\n");
582 # Do nothing, since the formatter has "paged" it for itself.
585 # Page it normally (internally)
587 if( -s $out ) { # Usual case:
588 $self->page($out, $self->{'output_to_stdout'}, $self->pagers);
592 $self->aside("Skipping $out (from $$found_list[0] "
593 . "via $$self{'formatter_class'}) as it is 0-length.\n");
595 push @{ $self->{'temp_file_list'} }, $out;
596 $self->unlink_if_temp_file($out);
600 $self->after_rendering(); # any extra cleanup or whatever
605 #..........................................................................
607 sub options_reading {
610 if( defined $ENV{"PERLDOC"} and length $ENV{"PERLDOC"} ) {
611 require Text::ParseWords;
612 $self->aside("Noting env PERLDOC setting of $ENV{'PERLDOC'}\n");
613 # Yes, appends to the beginning
614 unshift @{ $self->{'args'} },
615 Text::ParseWords::shellwords( $ENV{"PERLDOC"} )
617 DEBUG > 1 and print " Args now: @{$self->{'args'}}\n\n";
619 DEBUG > 1 and print " Okay, no PERLDOC setting in ENV.\n";
623 and print " Args right before switch processing: @{$self->{'args'}}\n";
625 Pod::Perldoc::GetOptsOO::getopts( $self, $self->{'args'}, 'YES' )
626 or return $self->usage;
629 and print " Args after switch processing: @{$self->{'args'}}\n";
631 return $self->usage if $self->opt_h;
636 #..........................................................................
638 sub options_processing {
642 my $podidx = "$Config{'archlib'}/pod.idx";
643 $podidx = "" unless -f $podidx && -r _ && -M _ <= 7;
644 $self->{'podidx'} = $podidx;
647 $self->{'output_to_stdout'} = 1 if $self->opt_T or ! -t STDOUT;
649 $self->options_sanity;
651 $self->opt_n("nroff") unless $self->opt_n;
652 $self->add_formatter_option( '__nroffer' => $self->opt_n );
654 # Adjust for using translation packages
655 $self->add_translator($self->opt_L) if $self->opt_L;
660 #..........................................................................
665 # The opts-counting stuff interacts quite badly with
666 # the $ENV{"PERLDOC"} stuff. I.e., if I have $ENV{"PERLDOC"}
667 # set to -t, and I specify -u on the command line, I don't want
668 # to be hectored at that -u and -t don't make sense together.
670 #my $opts = grep $_ && 1, # yes, the count of the set ones
671 # $self->opt_t, $self->opt_u, $self->opt_m, $self->opt_l
674 #$self->usage("only one of -t, -u, -m or -l") if $opts > 1;
677 # Any sanity-checking need doing here?
679 # But does not make sense to set either -f or -q in $ENV{"PERLDOC"}
680 if( $self->opt_f or $self->opt_q ) {
681 $self->usage("Only one of -f -or -q") if $self->opt_f and $self->opt_q;
683 "Perldoc is only really meant for reading one word at a time.\n",
684 "So these parameters are being ignored: ",
685 join(' ', @{$self->{'args'}}),
687 if @{$self->{'args'}}
692 #..........................................................................
694 sub grand_search_init {
695 my($self, $pages, @found) = @_;
698 if ($self->{'podidx'} && open(PODIDX, $self->{'podidx'})) {
699 my $searchfor = catfile split '::', $_;
700 $self->aside( "Searching for '$searchfor' in $self->{'podidx'}\n" );
704 push(@found, $_) if m,/$searchfor(?:\.(?:pod|pm))?\z,i;
706 close(PODIDX) or die "Can't close $$self{'podidx'}: $!";
710 $self->aside( "Searching for $_\n" );
714 push @found, $_ if $self->opt_m or $self->containspod($_);
720 # prepend extra search directories (including language specific)
721 push @searchdirs, @{ $self->{'extra_search_dirs'} };
723 # We must look both in @INC for library modules and in $bindir
724 # for executables, like h2xs or perldoc itself.
725 push @searchdirs, ($self->{'bindir'}, @INC);
726 unless ($self->opt_m) {
729 for ($i = 0; $trn = $ENV{'DCL$PATH;'.$i}; $i++) {
730 push(@searchdirs,$trn);
732 push(@searchdirs,'perl_root:[lib.pod]') # installed pods
735 push(@searchdirs, grep(-d, split($Config{path_sep},
739 my @files = $self->searchfor(0,$_,@searchdirs);
741 $self->aside( "Found as @files\n" );
744 # no match, try recursive search
745 @searchdirs = grep(!/^\.\z/s,@INC);
746 @files= $self->searchfor(1,$_,@searchdirs) if $self->opt_r;
748 $self->aside( "Loosely found as @files\n" );
752 ($self->opt_m ? "module" : "documentation") . " found for \"$_\".\n";
753 if ( @{ $self->{'found'} } ) {
754 print STDERR "However, try\n";
755 for my $dir (@{ $self->{'found'} }) {
756 opendir(DIR, $dir) or die "opendir $dir: $!";
757 while (my $file = readdir(DIR)) {
758 next if ($file =~ /^\./s);
759 $file =~ s/\.(pm|pod)\z//; # XXX: badfs
760 print STDERR "\tperldoc $_\::$file\n";
762 closedir(DIR) or die "closedir $dir: $!";
772 #..........................................................................
774 sub maybe_generate_dynamic_pod {
775 my($self, $found_things) = @_;
778 $self->search_perlfunc($found_things, \@dynamic_pod) if $self->opt_f;
780 $self->search_perlfaqs($found_things, \@dynamic_pod) if $self->opt_q;
782 if( ! $self->opt_f and ! $self->opt_q ) {
783 DEBUG > 4 and print "That's a non-dynamic pod search.\n";
784 } elsif ( @dynamic_pod ) {
785 $self->aside("Hm, I found some Pod from that search!\n");
786 my ($buffd, $buffer) = $self->new_tempfile('pod', 'dyn');
788 push @{ $self->{'temp_file_list'} }, $buffer;
789 # I.e., it MIGHT be deleted at the end.
791 my $in_list = $self->opt_f;
793 print $buffd "=over 8\n\n" if $in_list;
794 print $buffd @dynamic_pod or die "Can't print $buffer: $!";
795 print $buffd "=back\n" if $in_list;
797 close $buffd or die "Can't close $buffer: $!";
799 @$found_things = $buffer;
800 # Yes, so found_things never has more than one thing in
801 # it, by time we leave here
803 $self->add_formatter_option('__filter_nroff' => 1);
807 $self->aside("I found no Pod from that search!\n");
813 #..........................................................................
815 sub add_formatter_option { # $self->add_formatter_option('key' => 'value');
817 push @{ $self->{'formatter_switches'} }, [ @_ ] if @_;
819 DEBUG > 3 and printf "Formatter switches now: [%s]\n",
820 join ' ', map "[@$_]", @{ $self->{'formatter_switches'} };
825 #.........................................................................
827 sub new_translator { # $tr = $self->new_translator($lang);
831 my $pack = 'POD2::' . uc($lang);
832 eval "require $pack";
833 if ( !$@ && $pack->can('new') ) {
837 eval { require POD2::Base };
840 return POD2::Base->new({ lang => $lang });
843 #.........................................................................
845 sub add_translator { # $self->add_translator($lang);
848 my $tr = $self->new_translator($lang);
850 push @{ $self->{'translators'} }, $tr;
851 push @{ $self->{'extra_search_dirs'} }, $tr->pod_dirs;
853 $self->aside( "translator for '$lang' loaded\n" );
855 # non-installed or bad translator package
856 warn "Perldoc cannot load translator package for '$lang': ignored\n";
863 #..........................................................................
865 sub search_perlfunc {
866 my($self, $found_things, $pod) = @_;
868 DEBUG > 2 and print "Search: @$found_things\n";
870 my $perlfunc = shift @$found_things;
871 open(PFUNC, "<", $perlfunc) # "Funk is its own reward"
872 or die("Can't open $perlfunc: $!");
874 # Functions like -r, -e, etc. are listed under `-X'.
875 my $search_re = ($self->opt_f =~ /^-[rwxoRWXOeszfdlpSbctugkTBMAC]$/)
876 ? '(?:I<)?-X' : quotemeta($self->opt_f) ;
879 print "Going to perlfunc-scan for $search_re in $perlfunc\n";
881 my $re = 'Alphabetical Listing of Perl Functions';
882 if ( $self->opt_L ) {
883 my $tr = $self->{'translators'}->[0];
884 $re = $tr->search_perlfunc_re if $tr->can('search_perlfunc_re');
890 last if /^=head2 $re/;
893 # Look for our function
896 while (<PFUNC>) { # "The Mothership Connection is here!"
897 if ( m/^=item\s+$search_re\b/ ) {
901 last if $found > 1 and not $inlist;
911 ++$found if /^\w/; # found descriptive text
915 "No documentation for perl function `%s' found\n",
919 close PFUNC or die "Can't open $perlfunc: $!";
924 #..........................................................................
926 sub search_perlfaqs {
927 my( $self, $found_things, $pod) = @_;
931 my $search_key = $self->opt_q;
933 my $rx = eval { qr/$search_key/ }
935 Invalid regular expression '$search_key' given as -q pattern:
937 Did you mean \\Q$search_key ?
942 foreach my $file (@$found_things) {
943 die "invalid file spec: $!" if $file =~ /[<>|]/;
944 open(INFAQ, "<", $file) # XXX 5.6ism
945 or die "Can't read-open $file: $!\nAborting";
947 if ( m/^=head2\s+.*(?:$search_key)/i ) {
949 push @$pod, "=head1 Found in $file\n\n" unless $found_in{$file}++;
951 elsif (/^=head[12]/) {
959 die("No documentation for perl FAQ keyword `$search_key' found\n")
966 #..........................................................................
968 sub render_findings {
969 # Return the filename to open
971 my($self, $found_things) = @_;
973 my $formatter_class = $self->{'formatter_class'}
974 || die "No formatter class set!?";
975 my $formatter = $formatter_class->can('new')
976 ? $formatter_class->new
980 if(! @$found_things) {
981 die "Nothing found?!";
982 # should have been caught before here
983 } elsif(@$found_things > 1) {
985 "Perldoc is only really meant for reading one document at a time.\n",
986 "So these parameters are being ignored: ",
987 join(' ', @$found_things[1 .. $#$found_things] ),
991 my $file = $found_things->[0];
993 DEBUG > 3 and printf "Formatter switches now: [%s]\n",
994 join ' ', map "[@$_]", @{ $self->{'formatter_switches'} };
996 # Set formatter options:
997 if( ref $formatter ) {
998 foreach my $f (@{ $self->{'formatter_switches'} || [] }) {
999 my($switch, $value, $silent_fail) = @$f;
1000 if( $formatter->can($switch) ) {
1001 eval { $formatter->$switch( defined($value) ? $value : () ) };
1002 warn "Got an error when setting $formatter_class\->$switch:\n$@\n"
1005 if( $silent_fail or $switch =~ m/^__/s ) {
1006 DEBUG > 2 and print "Formatter $formatter_class doesn't support $switch\n";
1008 warn "$formatter_class doesn't recognize the $switch switch.\n";
1014 $self->{'output_is_binary'} =
1015 $formatter->can('write_with_binmode') && $formatter->write_with_binmode;
1017 my ($out_fh, $out) = $self->new_output_file(
1018 ( $formatter->can('output_extension') && $formatter->output_extension )
1020 $self->useful_filename_bit,
1023 # Now, finally, do the formatting!
1026 if(DEBUG() or $self->opt_v) {
1027 # feh, let 'em see it
1030 # The average user just has no reason to be seeing
1031 # $^W-suppressable warnings from the formatting!
1034 eval { $formatter->parse_from_file( $file, $out_fh ) };
1037 warn "Error while formatting with $formatter_class:\n $@\n" if $@;
1038 DEBUG > 2 and print "Back from formatting with $formatter_class\n";
1041 or warn "Can't close $out: $!\n(Did $formatter already close it?)";
1042 sleep 0; sleep 0; sleep 0;
1043 # Give the system a few timeslices to meditate on the fact
1044 # that the output file does in fact exist and is closed.
1046 $self->unlink_if_temp_file($file);
1049 if( $formatter->can( 'if_zero_length' ) ) {
1050 # Basically this is just a hook for Pod::Simple::Checker; since
1051 # what other class could /happily/ format an input file with Pod
1052 # as a 0-length output file?
1053 $formatter->if_zero_length( $file, $out, $out_fh );
1055 warn "Got a 0-length file from $$found_things[0] via $formatter_class!?\n"
1059 DEBUG and print "Finished writing to $out.\n";
1060 return($out, $formatter) if wantarray;
1064 #..........................................................................
1066 sub unlink_if_temp_file {
1067 # Unlink the specified file IFF it's in the list of temp files.
1068 # Really only used in the case of -f / -q things when we can
1069 # throw away the dynamically generated source pod file once
1070 # we've formatted it.
1072 my($self, $file) = @_;
1073 return unless defined $file and length $file;
1075 my $temp_file_list = $self->{'temp_file_list'} || return;
1076 if(grep $_ eq $file, @$temp_file_list) {
1077 $self->aside("Unlinking $file\n");
1078 unlink($file) or warn "Odd, couldn't unlink $file: $!";
1080 DEBUG > 1 and print "$file isn't a temp file, so not unlinking.\n";
1085 #..........................................................................
1087 sub MSWin_temp_cleanup {
1089 # Nothing particularly MSWin-specific in here, but I don't know if any
1090 # other OS needs its temp dir policed like MSWin does!
1094 my $tempdir = $ENV{'TEMP'};
1095 return unless defined $tempdir and length $tempdir
1096 and -e $tempdir and -d _ and -w _;
1099 "Considering whether any old files of mine in $tempdir need unlinking.\n"
1102 opendir(TMPDIR, $tempdir) || return;
1105 my $limit = time() - $Temp_File_Lifetime;
1107 DEBUG > 5 and printf "Looking for things pre-dating %s (%x)\n",
1112 while(defined($filespec = readdir(TMPDIR))) {
1114 $filespec =~ m{^perldoc_[a-zA-Z0-9]+_T([a-fA-F0-9]{7,})_[a-fA-F0-9]{3,}}s
1116 if( hex($1) < $limit ) {
1117 push @to_unlink, "$tempdir/$filespec";
1118 $self->aside( "Will unlink my old temp file $to_unlink[-1]\n" );
1121 printf " $tempdir/$filespec is too recent (after %x)\n", $limit;
1125 print " $tempdir/$filespec doesn't look like a perldoc temp file.\n";
1129 $self->aside(sprintf "Unlinked %s items of mine in %s\n",
1130 scalar(unlink(@to_unlink)),
1136 # . . . . . . . . . . . . . . . . . . . . . . . . .
1138 sub MSWin_perldoc_tempfile {
1139 my($self, $suffix, $infix) = @_;
1141 my $tempdir = $ENV{'TEMP'};
1142 return unless defined $tempdir and length $tempdir
1143 and -e $tempdir and -d _ and -w _;
1148 $spec = sprintf "%s\\perldoc_%s_T%x_%x%02x.%s", # used also in MSWin_temp_cleanup
1149 # Yes, we embed the create-time in the filename!
1154 defined( &Win32::GetTickCount )
1155 ? (Win32::GetTickCount() & 0xff)
1157 # Under MSWin, $$ values get reused quickly! So if we ran
1158 # perldoc foo and then perldoc bar before there was time for
1159 # time() to increment time."_$$" would likely be the same
1160 # for each process! So we tack on the tick count's lower
1161 # bits (or, in a pinch, rand)
1165 } while( -e $spec );
1169 while($counter < 50) {
1171 # If we are running before perl5.6.0, we can't autovivify
1174 $fh = Symbol::gensym();
1176 DEBUG > 3 and print "About to try making temp file $spec\n";
1177 return($fh, $spec) if open($fh, ">", $spec); # XXX 5.6ism
1178 $self->aside("Can't create temp file $spec: $!\n");
1181 $self->aside("Giving up on making a temp file!\n");
1182 die "Can't make a tempfile!?";
1185 #..........................................................................
1188 sub after_rendering {
1190 $self->after_rendering_VMS if IS_VMS;
1191 $self->after_rendering_MSWin32 if IS_MSWin32;
1192 $self->after_rendering_Dos if IS_Dos;
1193 $self->after_rendering_OS2 if IS_OS2;
1197 sub after_rendering_VMS { return }
1198 sub after_rendering_Dos { return }
1199 sub after_rendering_OS2 { return }
1201 sub after_rendering_MSWin32 {
1202 shift->MSWin_temp_cleanup() if $Temp_Files_Created;
1205 #..........................................................................
1207 #..........................................................................
1210 sub minus_f_nocase { # i.e., do like -f, but without regard to case
1212 my($self, $dir, $file) = @_;
1213 my $path = catfile($dir,$file);
1214 return $path if -f $path and -r _;
1217 or IS_VMS or IS_MSWin32
1220 # On a case-forgiving file system, or if case is important,
1221 # that is it, all we can do.
1222 warn "Ignored $path: unreadable\n" if -f _;
1229 foreach $p (splitdir $file){
1230 my $try = catfile @p, $p;
1231 $self->aside("Scrutinizing $try...\n");
1235 if ( $p eq $self->{'target'} ) {
1236 my $tmp_path = catfile @p;
1238 for (@{ $self->{'found'} }) {
1239 $path_f = 1 if $_ eq $tmp_path;
1241 push (@{ $self->{'found'} }, $tmp_path) unless $path_f;
1242 $self->aside( "Found as $tmp_path but directory\n" );
1245 elsif (-f _ && -r _) {
1249 warn "Ignored $try: unreadable\n";
1251 elsif (-d catdir(@p)) { # at least we see the containing directory!
1254 my $p_dirspec = catdir(@p);
1255 opendir DIR, $p_dirspec or die "opendir $p_dirspec: $!";
1256 while(defined( $cip = readdir(DIR) )) {
1257 if (lc $cip eq $lcp){
1259 last; # XXX stop at the first? what if there's others?
1262 closedir DIR or die "closedir $p_dirspec: $!";
1263 return "" unless $found;
1266 my $p_filespec = catfile(@p);
1267 return $p_filespec if -f $p_filespec and -r _;
1268 warn "Ignored $p_filespec: unreadable\n" if -f _;
1274 #..........................................................................
1276 sub pagers_guessing {
1280 push @pagers, $self->pagers;
1281 $self->{'pagers'} = \@pagers;
1284 push @pagers, qw( more< less notepad );
1285 unshift @pagers, $ENV{PAGER} if $ENV{PAGER};
1288 push @pagers, qw( most more less type/page );
1291 push @pagers, qw( less.exe more.com< );
1292 unshift @pagers, $ENV{PAGER} if $ENV{PAGER};
1296 unshift @pagers, 'less', 'cmd /c more <';
1298 push @pagers, qw( more less pg view cat );
1299 unshift @pagers, $ENV{PAGER} if $ENV{PAGER};
1303 if (($pagers[0] eq 'less') || ($pagers[0] eq '/usr/bin/less')) {
1304 unshift @pagers, '/usr/bin/less -isrR';
1308 unshift @pagers, $ENV{PERLDOC_PAGER} if $ENV{PERLDOC_PAGER};
1313 #..........................................................................
1315 sub page_module_file {
1316 my($self, @found) = @_;
1319 # Don't ever just pass this off to anything like MSWin's "start.exe",
1320 # since we might be calling on a .pl file, and we wouldn't want that
1321 # to actually /execute/ the file that we just want to page thru!
1322 # Also a consideration if one were to use a web browser as a pager;
1323 # doing so could trigger the browser's MIME mapping for whatever
1324 # it thinks .pm/.pl/whatever is. Probably just a (useless and
1325 # annoying) "Save as..." dialog, but potentially executing the file
1326 # in question -- particularly in the case of MSIE and it's, ahem,
1327 # occasionally hazy distinction between OS-local extension
1328 # associations, and browser-specific MIME mappings.
1330 if ($self->{'output_to_stdout'}) {
1331 $self->aside("Sending unpaged output to STDOUT.\n");
1334 foreach my $output (@found) {
1335 unless( open(TMP, "<", $output) ) { # XXX 5.6ism
1336 warn("Can't open $output: $!");
1341 print or die "Can't print to stdout: $!";
1343 close TMP or die "Can't close while $output: $!";
1344 $self->unlink_if_temp_file($output);
1346 return $any_error; # successful
1349 foreach my $pager ( $self->pagers ) {
1350 $self->aside("About to try calling $pager @found\n");
1351 if (system($pager, @found) == 0) {
1352 $self->aside("Yay, it worked.\n");
1355 $self->aside("That didn't work.\n");
1357 # Odd -- when it fails, under Win32, this seems to neither
1358 # return with a fail nor return with a success!!
1359 # That's discouraging!
1363 sprintf "Can't manage to find a way to page [%s] via pagers [%s]\n",
1365 join(' ', $self->pagers),
1369 DEBUG > 1 and print "Bailing out in a VMSish way.\n";
1371 use vmsish qw(status exit);
1378 # i.e., an UNSUCCESSFUL return value!
1381 #..........................................................................
1384 my($self, $dir, $file) = @_;
1386 unless( ref $self ) {
1387 # Should never get called:
1390 Carp::croak( join '',
1391 "Crazy ", __PACKAGE__, " error:\n",
1392 "check_file must be an object_method!\n",
1397 if(length $dir and not -d $dir) {
1398 DEBUG > 3 and print " No dir $dir -- skipping.\n";
1403 return $self->minus_f_nocase($dir,$file);
1407 my $path = $self->minus_f_nocase($dir,$file);
1408 if( length $path and $self->containspod($path) ) {
1410 " The file $path indeed looks promising!\n";
1414 DEBUG > 3 and print " No good: $file in $dir\n";
1419 #..........................................................................
1422 my($self, $file, $readit) = @_;
1423 return 1 if !$readit && $file =~ /\.pod\z/i;
1426 # Under cygwin the /usr/bin/perl is legal executable, but
1427 # you cannot open a file with that name. It must be spelled
1428 # out as "/usr/bin/perl.exe".
1430 # The following if-case under cygwin prevents error
1433 # Cannot open /usr/bin/perl: no such file or directory
1435 # This would work though
1437 # $ perldoc perl.pod
1439 if ( IS_Cygwin and -x $file and -f "$file.exe" )
1441 warn "Cygwin $file.exe search skipped\n" if DEBUG or $self->opt_v;
1446 open(TEST,"<", $file) or die "Can't open $file: $!"; # XXX 5.6ism
1449 close(TEST) or die "Can't close $file: $!";
1453 close(TEST) or die "Can't close $file: $!";
1457 #..........................................................................
1459 sub maybe_diddle_INC {
1462 # Does this look like a module or extension directory?
1464 if (-f "Makefile.PL" || -f "Build.PL") {
1466 # Add "." and "lib" to @INC (if they exist)
1467 eval q{ use lib qw(. lib); 1; } or die;
1469 # don't add if superuser
1470 if ($< && $> && -d "blib") { # don't be looking too hard now!
1471 eval q{ use blib; 1 };
1472 warn $@ if $@ && $self->opt_v;
1479 #..........................................................................
1481 sub new_output_file {
1483 my $outspec = $self->opt_d; # Yes, -d overrides all else!
1484 # So don't call this twice per format-job!
1486 return $self->new_tempfile(@_) unless defined $outspec and length $outspec;
1488 # Otherwise open a write-handle on opt_d!f
1491 # If we are running before perl5.6.0, we can't autovivify
1494 $fh = Symbol::gensym();
1496 DEBUG > 3 and print "About to try writing to specified output file $outspec\n";
1497 die "Can't write-open $outspec: $!"
1498 unless open($fh, ">", $outspec); # XXX 5.6ism
1500 DEBUG > 3 and print "Successfully opened $outspec\n";
1501 binmode($fh) if $self->{'output_is_binary'};
1502 return($fh, $outspec);
1505 #..........................................................................
1507 sub useful_filename_bit {
1508 # This tries to provide a meaningful bit of text to do with the query,
1509 # such as can be used in naming the file -- since if we're going to be
1510 # opening windows on temp files (as a "pager" may well do!) then it's
1511 # better if the temp file's name (which may well be used as the window
1512 # title) isn't ALL just random garbage!
1513 # In other words "perldoc_LWPSimple_2371981429" is a better temp file
1514 # name than "perldoc_2371981429". So this routine is what tries to
1515 # provide the "LWPSimple" bit.
1518 my $pages = $self->{'pages'} || return undef;
1519 return undef unless @$pages;
1521 my $chunk = $pages->[0];
1522 return undef unless defined $chunk;
1524 $chunk =~ s/\.\w+$//g; # strip any extension
1525 if( $chunk =~ m/([^\#\\:\/\$]+)$/s ) { # get basename, if it's a file
1530 $chunk =~ s/[^a-zA-Z0-9]+//g; # leave ONLY a-zA-Z0-9 things!
1531 $chunk = substr($chunk, -10) if length($chunk) > 10;
1535 #..........................................................................
1537 sub new_tempfile { # $self->new_tempfile( [$suffix, [$infix] ] )
1540 ++$Temp_Files_Created;
1543 my @out = $self->MSWin_perldoc_tempfile(@_);
1544 return @out if @out;
1545 # otherwise fall thru to the normal stuff below...
1549 return File::Temp::tempfile(UNLINK => 1);
1552 #..........................................................................
1554 sub page { # apply a pager to the output file
1555 my ($self, $output, $output_to_stdout, @pagers) = @_;
1556 if ($output_to_stdout) {
1557 $self->aside("Sending unpaged output to STDOUT.\n");
1558 open(TMP, "<", $output) or die "Can't open $output: $!"; # XXX 5.6ism
1561 print or die "Can't print to stdout: $!";
1563 close TMP or die "Can't close while $output: $!";
1564 $self->unlink_if_temp_file($output);
1566 # On VMS, quoting prevents logical expansion, and temp files with no
1567 # extension get the wrong default extension (such as .LIS for TYPE)
1569 $output = VMS::Filespec::rmsexpand($output, '.') if IS_VMS;
1571 $output =~ s{/}{\\}g if IS_MSWin32 || IS_Dos;
1572 # Altho "/" under MSWin is in theory good as a pathsep,
1573 # many many corners of the OS don't like it. So we
1574 # have to force it to be "\" to make everyone happy.
1576 foreach my $pager (@pagers) {
1577 $self->aside("About to try calling $pager $output\n");
1579 last if system("$pager $output") == 0;
1581 last if system("$pager \"$output\"") == 0;
1588 #..........................................................................
1591 my($self, $recurse,$s,@dirs) = @_;
1593 $s = VMS::Filespec::unixify($s) if IS_VMS;
1594 return $s if -f $s && $self->containspod($s);
1595 $self->aside( "Looking for $s in @dirs\n" );
1599 $self->{'target'} = (splitdir $s)[-1]; # XXX: why not use File::Basename?
1600 for ($i=0; $i<@dirs; $i++) {
1602 next unless -d $dir;
1603 ($dir = VMS::Filespec::unixpath($dir)) =~ s!/\z!! if IS_VMS;
1604 if ( (! $self->opt_m && ( $ret = $self->check_file($dir,"$s.pod")))
1605 or ( $ret = $self->check_file($dir,"$s.pm"))
1606 or ( $ret = $self->check_file($dir,$s))
1608 $ret = $self->check_file($dir,"$s.com"))
1610 $ret = $self->check_file($dir,"$s.cmd"))
1611 or ( (IS_MSWin32 or IS_Dos or IS_OS2) and
1612 $ret = $self->check_file($dir,"$s.bat"))
1613 or ( $ret = $self->check_file("$dir/pod","$s.pod"))
1614 or ( $ret = $self->check_file("$dir/pod",$s))
1615 or ( $ret = $self->check_file("$dir/pods","$s.pod"))
1616 or ( $ret = $self->check_file("$dir/pods",$s))
1618 DEBUG > 1 and print " Found $ret\n";
1623 opendir(D,$dir) or die "Can't opendir $dir: $!";
1624 my @newdirs = map catfile($dir, $_), grep {
1626 not /^auto\z/s and # save time! don't search auto dirs
1627 -d catfile($dir, $_)
1629 closedir(D) or die "Can't closedir $dir: $!";
1630 next unless @newdirs;
1631 # what a wicked map!
1632 @newdirs = map((s/\.dir\z//,$_)[1],@newdirs) if IS_VMS;
1633 $self->aside( "Also looking in @newdirs\n" );
1634 push(@dirs,@newdirs);
1640 #..........................................................................
1642 my $already_asserted;
1643 sub assert_closing_stdout {
1646 return if $already_asserted;
1648 eval q~ END { close(STDOUT) || die "Can't close STDOUT: $!" } ~;
1649 # What for? to let the pager know that nothing more will come?
1652 $already_asserted = 1;
1657 #..........................................................................
1659 sub tweak_found_pathnames {
1660 my($self, $found) = @_;
1662 foreach (@$found) { s,/,\\,g }
1667 #..........................................................................
1669 #..........................................................................
1671 sub am_taint_checking {
1673 die "NO ENVIRONMENT?!?!" unless keys %ENV; # reset iterator along the way
1674 my($k,$v) = each %ENV;
1675 return is_tainted($v);
1678 #..........................................................................
1680 sub is_tainted { # just a function
1682 my $nada = substr($arg, 0, 0); # zero-length!
1683 local $@; # preserve the caller's version of $@
1684 eval { eval "# $nada" };
1685 return length($@) != 0;
1688 #..........................................................................
1690 sub drop_privs_maybe {
1693 # Attempt to drop privs if we should be tainting and aren't
1694 if (!(IS_VMS || IS_MSWin32 || IS_Dos
1697 && ($> == 0 || $< == 0)
1698 && !$self->am_taint_checking()
1700 my $id = eval { getpwnam("nobody") };
1701 $id = eval { getpwnam("nouser") } unless defined $id;
1702 $id = -2 unless defined $id;
1704 # According to Stevens' APUE and various
1705 # (BSD, Solaris, HP-UX) man pages, setting
1706 # the real uid first and effective uid second
1707 # is the way to go if one wants to drop privileges,
1708 # because if one changes into an effective uid of
1709 # non-zero, one cannot change the real uid any more.
1711 # Actually, it gets even messier. There is
1712 # a third uid, called the saved uid, and as
1713 # long as that is zero, one can get back to
1714 # uid of zero. Setting the real-effective *twice*
1715 # helps in *most* systems (FreeBSD and Solaris)
1716 # but apparently in HP-UX even this doesn't help:
1717 # the saved uid stays zero (apparently the only way
1718 # in HP-UX to change saved uid is to call setuid()
1719 # when the effective uid is zero).
1722 $< = $id; # real uid
1723 $> = $id; # effective uid
1724 $< = $id; # real uid
1725 $> = $id; # effective uid
1727 if( !$@ && $< && $> ) {
1728 DEBUG and print "OK, I dropped privileges.\n";
1729 } elsif( $self->opt_U ) {
1730 DEBUG and print "Couldn't drop privileges, but in -U mode, so feh."
1732 DEBUG and print "Hm, couldn't drop privileges. Ah well.\n";
1733 # We used to die here; but that seemed pointless.
1739 #..........................................................................
1745 # See "perldoc perldoc" for basic details.
1747 # Perldoc -- look up a piece of documentation in .pod format that
1748 # is embedded in the perl installation tree.
1752 # See ChangeLog in CPAN dist for Pod::Perldoc for later notes.
1754 # Version 3.01: Sun Nov 10 21:38:09 MST 2002
1755 # Sean M. Burke <sburke@cpan.org>
1756 # Massive refactoring and code-tidying.
1757 # Now it's a module(-family)!
1758 # Formatter-specific stuff pulled out into Pod::Perldoc::To(Whatever).pm
1759 # Added -T, -d, -o, -M, -w.
1760 # Added some improved MSWin funk.
1764 # Version 2.05: Sat Oct 12 16:09:00 CEST 2002
1765 # Hugo van der Sanden <hv@crypt.org>
1766 # Made -U the default, based on patch from Simon Cozens
1767 # Version 2.04: Sun Aug 18 13:27:12 BST 2002
1768 # Randy W. Sims <RandyS@ThePierianSpring.org>
1769 # allow -n to enable nroff under Win32
1770 # Version 2.03: Sun Apr 23 16:56:34 BST 2000
1771 # Hugo van der Sanden <hv@crypt.org>
1772 # don't die when 'use blib' fails
1773 # Version 2.02: Mon Mar 13 18:03:04 MST 2000
1774 # Tom Christiansen <tchrist@perl.com>
1775 # Added -U insecurity option
1776 # Version 2.01: Sat Mar 11 15:22:33 MST 2000
1777 # Tom Christiansen <tchrist@perl.com>, querulously.
1778 # Security and correctness patches.
1779 # What a twisted bit of distasteful spaghetti code.
1784 # Version 1.15: Tue Aug 24 01:50:20 EST 1999
1785 # Charles Wilson <cwilson@ece.gatech.edu>
1786 # changed /pod/ directory to /pods/ for cygwin
1787 # to support cygwin/win32
1788 # Version 1.14: Wed Jul 15 01:50:20 EST 1998
1789 # Robin Barker <rmb1@cise.npl.co.uk>
1790 # -strict, -w cleanups
1791 # Version 1.13: Fri Feb 27 16:20:50 EST 1997
1792 # Gurusamy Sarathy <gsar@activestate.com>
1793 # -doc tweaks for -F and -X options
1794 # Version 1.12: Sat Apr 12 22:41:09 EST 1997
1795 # Gurusamy Sarathy <gsar@activestate.com>
1796 # -various fixes for win32
1797 # Version 1.11: Tue Dec 26 09:54:33 EST 1995
1798 # Kenneth Albanowski <kjahds@kjahds.com>
1799 # -added Charles Bailey's further VMS patches, and -u switch
1800 # -added -t switch, with pod2text support
1802 # Version 1.10: Thu Nov 9 07:23:47 EST 1995
1803 # Kenneth Albanowski <kjahds@kjahds.com>
1804 # -added VMS support
1805 # -added better error recognition (on no found pages, just exit. On
1806 # missing nroff/pod2man, just display raw pod.)
1807 # -added recursive/case-insensitive matching (thanks, Andreas). This
1808 # slows things down a bit, unfortunately. Give a precise name, and
1811 # Version 1.01: Tue May 30 14:47:34 EDT 1995
1812 # Andy Dougherty <doughera@lafcol.lafayette.edu>
1813 # -added pod documentation.
1814 # -added PATH searching.
1815 # -added searching pod/ subdirectory (mainly to pick up perlfunc.pod
1822 # Cache the directories read during sloppy match
1823 # (To disk, or just in-memory?)
1825 # Backport this to perl 5.005?
1827 # Implement at least part of the "perlman" interface described
1828 # in Programming Perl 3e?