#!/usr/bin/perl -w

# A simple dictionary.  Take command line arguments to
# either read+initialize the on-disk DB files, or to 
# respond to an inquiry.

use strict;                       # Strict syntax checking
use DB_File;                      # Used for db tie 

# Function prototypes:
sub dobuild($);
sub doquery($$);
sub usage();

# Variable definition:
my $dbfile = "dict.db";            # Where we'll store the word dictionary

# Get command-line arguments:
if ($#ARGV != 1) { die usage; }

# See page 124 in "Programming Perl" for switch/case examples:
SWITCH : {

    if ($ARGV[0] eq "-b") {
	dobuild($ARGV[1]);
	last SWITCH;
    }
    if ($ARGV[0] eq "-q") {
	doquery($ARGV[1], "q");
	last SWITCH;
    }
    if ($ARGV[0] eq "-r") {
	doquery($ARGV[1], "r");
	last SWITCH;
    }

    # The switch failed:
    usage();
}

# All done:
exit;


# Build input.  See section 14.1 in the "Cookbook" for more detail.
sub dobuild($) {
    my $infile = shift;
    my $ct = 0;                      # Count words input
    
    # This opens a database file (it might already exist) and
    # ties our array to it:
    my %assoc;
    tie %assoc, "DB_File", $dbfile
	or die "Tie to $dbfile failed: $!\n";

    # Local function variables:
    my $orig; my $new;

    # Variations: these are simply word endings (order matters in this example)
    my @endings = ( "es", "ed", "s", "ing" );

    # Get input:
    open (FH, "<$infile") or die "Open of $infile failed: $!\n";
    while (<FH>) {
	$orig = $_;
	chomp($orig);
	# Key=word variation
	# Value=original word
	# First: store original word
	$assoc{$orig} = $orig;
        $ct++;

	# Second: map to lower case
	$new = lc($orig);
	if (! exists ($assoc{$new})) {
	    $assoc{$new} = $orig;
	    $ct++;
	}

	# Last: Loop for each variation.  Stop after we find one variation.
	# This simply truncates the variation.
	foreach (@endings) {
	    if ( /${_}$/ ) {
		$new = $orig;
		$new =~ s/${_}//;
		if (! exists ($assoc{$new})) {
		    $assoc{$new} = $orig;
		    $ct++;
		}
		last;
	    }
	}
	# Done with this input term
    }

    untie %assoc;
    close(FH);
    exit $ct;
}


# Query the dictionary:
sub doquery($$) {
    my $word = shift;
    my $quiet = shift;

    my %assoc; 
    tie %assoc, "DB_File", $dbfile
	or die "Tie to $dbfile failed: $!\n";
    
    if (! exists ($assoc{$word})) {
	if ($quiet eq "q") {
	    exit 0; # No matches, exit silently
	} else {
	    print "No matches for \'$word\'\n";
	}
    } else {
	if ($quiet ne "q") {
	    exit 0; # Got a match, exit silently
	} else {
	    print "Word \'$word\" is in dictionary, root=\'"
		. $assoc{$word} . "\'\n";
	}
    }

    untie %assoc;
}



# Print command-line usage
sub usage() {
    print "Usage:\t$0 -b infile : to build a dictionary\n";
    print "\t$0 -q word : to query a word, listing matches\n";
    print "\t$0 -r word : to query a word, silent output unless no matches\n";
    exit 1;
}
