Hashing Variable-Record-Length Files

########   Random-Access Variable-Length (Text) File Processing With Indexing

#!/usr/bin/perl 

die "Usage: $0 filename\n" if @ARGV != 1;
open(F, "$ARGV[0]") || die "Cannot open $ARGV[0] for reading.\n";
die "File is empty!\n" if -z $ARGV[0];

$index = 1;
$offsets[$index] = 0;  #  Offsets[0] not assigned because there's no line zero!
$offsets[++$index] = tell(F) while (<F>);
$index--;

while(print ("Enter line numbers:  "),  ($_ = <STDIN>) !~ /^\s*quit\s*$/i)
{
     next if /^\s*$/;    #  No response.  Just re-prompt.
     if ($_ !~ /^\s*\d+\s*(\d+\s*)?$/)   # Must be one or two digit strings!
     {
          print "Legal entries consist of one or two positive integers!\n";
          next;
     }
     @lines = m/\d+/g;  #  Gather the digit string(s).
     $lines[1] = $lines[0] if @lines == 1;
     if (($lines[0] > $index) || ($lines[1] > $index) || ($lines[0] == 0) ||
         ($lines[1] == 0))
     {
          print "Legal line numbers are 1 through $index!\n";
          next;
     }
     if ($lines[1] < $lines[0])
     {
          print "Improper order of numbers.\n";
          next;
     }

#  Go to offset of first user-specified line.
     seek(F, $offsets[$lines[0]], 0);
     open(MORE,"|more") || die "Cannot open more filter.\n";
     foreach $linenum ($lines[0]..$lines[1])
     {
          printf  MORE "%-5s:%s", $linenum, scalar(<F>);
     } 
     close(MORE);
}
#######################  Sample Program Session  #########################

$ textindex.pl asg55.pl
Enter line numbers:  2 90
Legal line numbers are 1 through 58!
Enter line numbers:  -1 10
Legal entries consist of one or two integers!
Enter line numbers:  2 25
2    :    
3    :    open(PHONE, "phonebook") || die "Could not open phonebook.\n";
4    :    
5    :    while (<PHONE>)
6    :    {
7    :        chomp($_);
8    :        ($name, $ext) = split(/:/, $_);
9    :        $byname{$name} = $ext;
10   :    }
11   :    
12   :    %byext = reverse(%byname);
13   :    close(PHONE);
14   :    
15   :    while (($name_or_ext = get_and_clean_name()) ne "Quit")
16   :    {
17   :        next if $name_or_ext =~ /^\s*$/;
18   :        if ($name_or_ext =~ /^\d/)   ##### It's an extension.
19   :        {
20   :             if (!exists($byext{$name_or_ext}))
21   :             {
22   :                  print "Nobody has that extension.\n\n";
23   :             }
[7m--More--[m   ###  Notice the "footprint" of more.
24   :             else
25   :             {

Enter line numbers:  8 6
Improper order of numbers.

Enter line numbers:  1111
Legal line numbers are 1 through 58!

Enter line numbers:  1 2 3
Legal entries consist of one or two positive integers!
Enter line numbers:  
Enter line numbers:     qUiT
$