3 # $Id: Info.pm,v 1.1 1999/07/30 18:46:36 mdw Exp $
5 # Manipulation and reading of Info files
10 #----- Licensing notice -----------------------------------------------------
12 # This file is part of sw-tools.
14 # sw-tools is free software; you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation; either version 2 of the License, or
17 # (at your option) any later version.
19 # sw-tools is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
24 # You should have received a copy of the GNU General Public License
25 # along with sw-tools; if not, write to the Free Software Foundation,
26 # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 #----- Revision history -----------------------------------------------------
31 # Revision 1.1 1999/07/30 18:46:36 mdw
32 # New CGI script for browsing installed software and documentation.
35 #----- Package preamble -----------------------------------------------------
42 @EXPORT_OK = qw(setpath
);
44 #----- Low-level twiddling --------------------------------------------------
46 @infopath = ("/usr/info");
48 # --- @setpath(PATH...)@ ---
50 # Sets the Info search path.
56 # --- @getname(INFO)@ ---
58 # Given the name of an Info manual, find the actual file.
64 foreach my $p (@infopath) {
67 foreach my $suff ("", "-info", ".info") {
68 return $f . $suff if -r
$f . $suff;
69 return $f . $suff . ".gz" if -r
$f . $suff . ".gz";
75 # --- @snarf(FILE)@ ---
77 # Snarf a file into a string, given its name. Handles compressed files.
85 my $p = IO
::Pipe
->new();
87 defined($kid) or return undef;
90 dup2
($p->fileno(), 1);
91 exec("gzip", "-dc", $f);
95 $snarf = $p->getline();
99 my $fh = IO
::File
->new($f, O_RDONLY
) or return undef;
100 $snarf = $fh->getline();
106 #----- An Info-file object --------------------------------------------------
108 # --- @node(NAME)@ ---
110 # Picks an individual node out of an Info file.
113 my ($me, $node) = @_;
118 # --- If there's an index, it will help me find the node ---
121 $offset = $me->{index}{lc($node)};
123 # --- Maybe the offset is into a different file ---
127 PAIR
: foreach my $pair (@
{$me->{indir
}}) {
128 if ($pair->[0] <= $offset) {
129 ($loff, $file) = @
$pair;
134 return undef unless $file;
139 # --- Fetch the file ---
144 $fn = "$me->{dir}/$file", -r
$fn or
145 $fn = "$me->{dir}/$file.gz", -r
$fn or
148 if ($me->{cache
}{$fn}) {
149 $file = $me->{cache
}{$fn};
151 $file = $me->{cache
}{$fn} = snarf
($fn) or return undef;
157 # --- Dig through the file to find the right node ---
161 if ($file =~ / \G
.*\1f\n
169 $offset = 0, next GASP
if $offset;
176 # --- @load(NAME)@ ---
178 # Loads a file into an Info object.
181 my ($me, $file) = @_;
182 my $f = getname
($file) or return undef;
183 my $c = snarf
($f) or return undef;
185 # --- Read the index, and maybe snarf in the indirection file ---
187 if (my ($index) = ($c =~ /\1f\nTag Table:\n([^\1f]*)\1f\nEnd Tag Table\n/s)) {
189 while ($index =~ /Node: *([^\n\7f]*)\7f(\d+)\n/sg) { $index{lc($1)} = $2; }
190 $me->{index} = \
%index;
191 if ($index =~ /^\(Indirect\)/ and
192 my ($indir) = ($c =~ /\1f\nIndirect:\n([^\1f]*)\1f\n/s)) {
194 while ($indir =~ /([^\n:]*): *(\d+)\n/sg) { push(@indir, [$2, $1]); }
195 $me->{indir
} = \
@indir;
199 ($me->{dir
} = $f) =~ s
:/[^/]*$::;
204 # --- @new([NAME])@ ---
206 # Makes a new Info file and returns it to the caller.
209 my ($class, $file) = @_;
210 my $me = bless {}, $class;
211 return $me->load($file) if $file;
215 #----- That's all, folks ----------------------------------------------------