mjd-perl-pm on Thu, 17 Feb 2000 11:45:52 -0500 (EST)


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: Perl Ripping Event


This is a subroutine library for a larger program.  The library is
supposed to read through GNU `info' files.  The instructions that came
with it say:

        To use the functions:  Call
        
        	&open_info_file(INFO_FILENAME);
        
        to open the filehandle `INFO' to the named info file.
        Then call 
        
        	&get_next_node;
        
        repeatedly to read the next node in the info file; the variables
        	$info_file
        	$info_node
        	$info_prev
        	$info_next
        	$info_up
        
        are set if the corresponding fields appear in the node's
        header, and if the node has a menu, it is loaded into
        %info_menu.  When `get_next-node' returns false, you have
        reached end-of-file or there has been an error.


Those if you with linux boxes probably have an example of an info file
handy.  I did not include one here because I thought it might be more
interesting for the people who had not seen one to deduce the
structure of the file from the code below.

One final note:  This code was taken from a comp.lang.perl posting
from around 1994.  I reproduce it exactly typograhical errors and all.

================================================================

# Read next node into global variables.  Assumes that file pointer is
# positioned at the header line that starts a node.  Leaves file
# pointer positioned at header line of next node.
# Programmer: note that nodes are separated by a "\n\037\n" sequence.
# Reutrn true on success, false on failure
sub read_next_node {
    undef %info_menu;
    $_ = <INFO>;		# Header line
    if (eof(INFO)) {
	return &start_next_part && &read_next_node;
    }

    ($info_file) = /File:\s*([^,]*)/;
    ($info_node) = /Node:\s*([^,]*)/;
    ($info_prev) = /Prev:\s*([^,]*)/;
    ($info_next) = /Next:\s*([^,]*)/;
    ($info_up)   = /Up:\s*([^,]*)/;

    $_ = <INFO> until /^(\* Menu:|\037)/ || eof(INFO);
    if (eof(INFO)) {
	return &start_next_part;
    } elsif (/^\037/) { 
	return 1;		# end of node, so return success.
    }

    # read menu
    local($key, $ref);
    while (<INFO>) {    
	return 1 if /^\037/;    # end of node, menu is finished, success.
	next unless /^\* \S/;   # next unless lines is a menu item
	if (/^\* ([^:]*)::/) {
	    $key = $ref = $1;
	} elsif (/^\* ([^:]*):\s*([^.]*)[.]/) {
	    ($key, $ref) = ($1, $2);
	} else {
	    print STDERR "Couldn't parse menu item\n\t$_";
	    next;
	}
	$info_menu{$key} = $ref;
    }
    # end-of-file also terminates the node successfully.
    # start up the next file before continuing.
    &start_next_part;
    return 1;
}
	
# Discard commentary before first node of info file
sub start_info_file {
    $_ = <INFO> until (/^\037/ || eof(INFO));
    return &start_next_part if (eof(INFO)) ;
    return 1;
}

# Look for next part of multi-part info file.  
# Return 0 (normal failure) if it isn't there---that just means
# we ran out of parts.  die on some other kind of failure.
sub start_next_part {
    local($path, $basename, $ext);
    if ($info_filename =~ /\//) {
	($path, $basename) = ( $info_filename =~ /^(.*)\/(.*)$/ );
    } else {
	$basename = $info_filename;
	$path = "";
    }
    if ($basename =~ /-\d*$/) {
	($basename, $ext) = ($basename =~ /^([^-]*)-(\d*)$/);
    } else {
	$ext = 0;
    }
    $ext++;
    $info_filename = "$path/$basename-$ext";
    close(INFO);
    if (! (open(INFO, "$info_filename")) ) {
	if ($! eq "No such file or directory") {
	    return 0;
	} else {
	    die "Couldn't open $info_filename: $!";
	}
    }
    return &start_info_file;
}

sub open_info_file {
    ($info_filename) = @_;
    (open(INFO, "$info_filename")) || die "Couldn't open $info_filename: $!";
    return &start_info_file;
}
**Majordomo list services provided by PANIX <URL:http://www.panix.com>**
**To Unsubscribe, send "unsubscribe phl" to majordomo@lists.pm.org**