/* File: HashExample.m - HashFile Example ('phone number to word translator)
 *
 * By: Christopher Lane
 * Symbolic Systems Resources Group
 * Knowledge Systems Laboratory
 * Stanford University
 *
 * Date: 22 March 1991
 *
 * Copyright: 1990, 1991 by The Leland Stanford Junior University.  This
 * program may be distributed without restriction for non-commercial use.
 */

#import <stdlib.h>
#import <stdio.h>
#import <string.h>
#import <ctype.h>
#import <getopt.h>

#import "HashFile.h"

extern char *basename(char *s); // #import <text/pathutil.h>

#define INTEGER @encode(int)
#define STRING @encode(char *)

#define OPTIONSTRING "bdh:"
#define USAGE "usage: %s [-h database] [-d] [-b < wordlist] \n"

typedef enum { BUILD = 'b', DUMP = 'd', HASHFILE = 'h' } OPTIONS;
typedef enum { PROGRAM } ARGUMENTS;

#define BUFFERSIZE 1024
#define DIGITMAX (7)

#ifndef DATABASE
#define DATABASE "PhoneWords"
#endif

const char *letters = "abcdefghijklmnoprstuvwxyABCDEFGHIJKLMNOPRSTUVWXY";
const char *numbers = "222333444555666777888999222333444555666777888999";

void buildTable(id table)
{		
	char *s, *idx = NULL, value[BUFFERSIZE], buffer[BUFFERSIZE];
	unsigned int key;
		
	[table empty];

	while(gets(value) != NULL) {
		if(strlen(s = value) > DIGITMAX) continue;
		key = 0;
		while(*s)
			if((idx = index(letters, *s++)) == NULL) break;
			else key = (key * 10) + ( numbers[idx - letters] - '0' );
		if(idx == NULL) continue;
#ifdef DEBUG
		printf("<%d\t%s\n", key, value);
#endif
		if([table isKey:(void *) key])
			s = strcat(strcat(strcpy(buffer, (char *) [table valueForKey:(void *) key]), " "), value);
		else s = value;
		
		[table insertKey:(void *) key value:(void *) NXCopyStringBuffer(s)];
		} /* while */
}

void dumpTable(id table)
{
	void *key, *value;
	NXHashState state = [table initState];

	while([table nextState:&state key:&key value:&value])
		(void) printf("%d\t%s\n", (int) key, (char *) value);
}

void main(int argc, char *argv[])
{
	id table;
	int key, option, nitems, status = EXIT_SUCCESS;
	char *database = DATABASE;
	BOOL buildFlag = NO, dumpFlag = NO;
		
	while((option = getopt(argc, argv, OPTIONSTRING)) != EOF)
		switch(option) {
		case BUILD : buildFlag = YES; break;
		case DUMP : dumpFlag = YES; break;
		case HASHFILE : database = optarg; break;
		default : status = EXIT_FAILURE;
		} /* while */

	if(optind < argc || status == EXIT_FAILURE) {
		(void) fprintf(stderr, USAGE, basename(argv[PROGRAM]));
		exit(EXIT_FAILURE);
		} /* if */

	if((buildFlag || [HashFile isHashFile:database]) &&
	   (table = [[HashFile alloc] initFromFile:database keyDesc:INTEGER valueDesc:STRING]) != nil) {
		if(buildFlag) buildTable(table);
		if(dumpFlag) dumpTable(table);
		if(!buildFlag && !dumpFlag) {
			while((nitems = scanf("%d", &key)) != EOF && nitems == 1)
				if([table isKey:(void *) key])
					(void) printf("%d\t%s\n", key, (char *) [table valueForKey:(void *) key]);
			} /* if */
		[table free];
		} /* if */
	else (void) fprintf(stderr, "%s: Can't open %s.\n", basename(argv[PROGRAM]), database, status = EXIT_FAILURE);

	exit(status);
}
